[Interest] Strange visibility problem after updating entities in Qt3D

Helmut Mülner helmut.muelner at gmail.com
Wed Oct 4 15:37:56 CEST 2017


Hi Paul,

 

thank you for your tips, I think you diagnosed the problem correctly.

 

Von: paul.lemire [mailto:paul.lemire] Im Auftrag von Paul Lemire
Gesendet: Mittwoch, 4. Oktober 2017 07:05



 [
]

Now I want to show another rail (it may have fewer or more parts) and
another set of defects.

The view from the side looks good (see rail2.jpg).

But if I tilt the view, the visibility of the first two boxes is wrong.

[
]

Did you specify a custom FrameGraph in QRenderSettings?

No.


What I think is happening is that sometimes the drawing order is correct,
sometimes it's not. So you end up in cases where the RailDefect are drawn
before the RailParts which would explain the issue.
In Qt3D, when using the default provided FrameGraph the drawing order isn't
defined by the position in which an Entity is in the tree hierarchy of the
scene.

 

I obviously misinterpreted this information from the „Qt 3D Render
Framegraph” documentation:

 

The Qt 3D renderer performs a depth first traversal of the framegraph tree.
Note that, because the traversal is depth first, the order in which you
define nodes is important.


You can control that drawing order by having a custom FrameGraph tree and
using the elements QLayer and QLayerFilter.
You would basically need to have a QLayer for the rail, a QLayer for the
defects. Then in your FrameGraph you would first have a branch with a
QLayerFilter that selects entities with the layer for the rail, then a
second branch which would select entities with the defect layer. That way
you will be sure that at all times the rail is rendered first, followed by
the defects.

 

You lost me here.

I have this code (copied from somewhere without understanding it fully):

 

void RailEntityPrivate::initEntity()

{

    Q_Q(RailEntity);

    auto* renderSettings = new Qt3DRender::QRenderSettings();

    auto* viewport = new Qt3DRender::QViewport();

    viewport->setNormalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f));

    auto* renderSurfaceSelector = new
Qt3DRender::QRenderSurfaceSelector(viewport);

    auto* layerFilter = new Qt3DRender::QLayerFilter(renderSurfaceSelector);

    layerFilter->setEnabled(false);

    auto* cameraSelector = new Qt3DRender::QCameraSelector(layerFilter);

    cameraSelector->setCamera(camera);

 

    auto* clearBuffer = new Qt3DRender::QClearBuffers(cameraSelector);

 
clearBuffer->setBuffers(Qt3DRender::QClearBuffers::ColorDepthStencilBuffer);

    clearBuffer->setClearColor("#EEEEEE");

 

 

    renderSettings->setActiveFrameGraph(viewport);

    q->addComponent(renderSettings);

    camera->setPosition(QVector3D(0.0f, 5.0f, 0.0f) + QVector3D(-25.0f,
0.0f, 0.0f));

    camera->setViewCenter(QVector3D(0.0f, 0.0f, 0.0f));

    camera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));

    camera->setFarPlane(2000.0f);

    auto camController = new Qt3DExtras::QOrbitCameraController(q);

    camController->setLinearSpeed(300.0f);

    camController->setLookSpeed(180.0f);

    camController->setCamera(camera);

 
renderSettings->pickingSettings()->setPickMethod(Qt3DRender::QPickingSetting
s::TrianglePicking);

    auto objectPicker = new Qt3DRender::QObjectPicker(q);

    q->addComponent(objectPicker);

    QObject::connect(objectPicker, &Qt3DRender::QObjectPicker::clicked, q,
&RailEntity::onClicked);

    railParts = new Qt3DCore::QEntity(q);

    railDefects = new Qt3DCore::QEntity(q);

}

 

I studied the (minimal) Qt3D documentation, the tests and the examples but
could not find how to do this. I have the feeling that the Qt3d
documentation and reference material assumes that the user already is an
OpenGL expert. I am an experienced C++ and Qt developer but relatively new
to OpenGL and Qt3D.

 

My remaining problems:

- How do I define a custom FrameGraph tree?

- Do I need a QLayerFilter for each layer?

- How do I define a branch in the FrameGraph?

 

I tried to add this to the end of initEntity():

 

    partsLayer = new  Qt3DRender::QLayer(railParts);

    partsLayer->setRecursive(true);

    railParts->addComponent(partsLayer);

    defectsLayer = new  Qt3DRender::QLayer(railDefects);

    defectsLayer->setRecursive(true);

    railDefects->addComponent(partsLayer);

    layerFilter->addLayer(partsLayer);

    layerFilter->addLayer(defectsLayer);

 

Now I get a Windows error message after starting the program: entry point
missing in DLL: createNodeCreationChange...

I am using Qt 5.9.1 prebuilt msvc2017_64.




 

To update the scene I remove all Rail.* entities and insert the new ones.

 

These are the relevant parts of this code:

 

void deleteChildrenRecursively(const Qt3DCore::QNodeVector& vector)

{

    Qt3DCore::QNode* nullParent = nullptr;

    for (auto* node : vector) {

        auto* entity = dynamic_cast<Qt3DCore::QEntity*>(node);

qobject_cast would be more appropriate here
If you set the parenting correctly on your elements, you should be able to
delete only the parent of all the entities you want to delete which would
take care of doing the recursive deletion automatically for you.
You may want to add another Entity just for that purpose of grouping your
rail parts.
[
]

I know that (have written Qt  programs since Qt-2.3.2), I just wanted to be
sure the effect did not come from some left-over nodes in the framegraph

 

Cheers,

Helmut

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20171004/a441217b/attachment.html>


More information about the Interest mailing list