[Interest] Strange visibility problem after updating entities in Qt3D

Helmut Mülner helmut.muelner at gmail.com
Thu Oct 5 13:41:39 CEST 2017


Hi Paul,

 

thank you very much for your help – updates of my defects work finally.

I also understand now why Qt 5.10 introduced the “recursive” property for
layers ;-)

 

A simplified version of this code would give a fine example for the QLayer
documentation.

BTW this documentation has some namespace problems since 5.9.

 

I hope to be able to attend the Qt world summit next year, so I can buy you
a beer etc.

 

Big Thanks,

Helmut

 

Von: paul.lemire [mailto:paul.lemire] Im Auftrag von Paul Lemire
Gesendet: Donnerstag, 5. Oktober 2017 11:46
An: Helmut Mülner <helmut.muelner at gmail.com>; interest at qt-project.org
Betreff: Re: AW: [Interest] Strange visibility problem after updating
entities in Qt3D

 

Hi Helmut,

In Qt3D there is the scene tree called the SceneGraph and in QRenderSettings
you can specify another tree called the FrameGraph. The FrameGraph basically
configures the renderer to match your needs.

In your case what you would need is to:

Create 2 layers

QLayer *railsLayer;

QLayer *defectsLayers;

For each Entity of your scene, add as a component either railsLayer or
defectsLayer depending on what the Entity represents.

Then the FrameGraph would have to do

1) Render all the entities which have railsLayer as a layer 

2) Render all the entities which have defectsLayer as a layer

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* cameraSelector = new
Qt3DRender::QCameraSelector(renderSurfaceSelector); 

cameraSelector->setCamera(camera);


// All of the above will be common to the two branches

// Branch 1 needs to clear the screen and render all entities with layer
railsLayer
auto* clearBuffer = new Qt3DRender::QClearBuffers(cameraSelector); 

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

clearBuffer->setClearColor("#EEEEEE");

auto* layerFilterRails = new Qt3DRender::QLayerFilter(clearBuffer);

layerFilterRails->addLayer(railsLayer);


// Branch 2 needs to render all entities with layer defectsLayer

auto* layerFilterDefects = new Qt3DRender::QLayerFilter(cameraSelector);

layerFilterDefects->addLayer(defectsLayers);

 

It's easier to visualize in QML

 

RenderSettings {
    frameGraph: Viewport {
        RenderSurfaceSelector {
            CameraSelector {
            
                // Branch 1
                ClearBuffers {
                    buffers: ClearBuffers.ColorDepthBuffer
                    LayerFilter { layers: railsLayer }
                }

                // Branch 2
                LayerFilter { layers: defectsLayer }
            }
        }
    }
}

 

Hopefully that answers your questions,

 

Paul

    

On 10/04/2017 03:37 PM, Helmut Mülner wrote:

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

 





-- 
Paul Lemire | paul.lemire at kdab.com <mailto:paul.lemire at kdab.com>  | Senior
Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel: France +33 (0)4 90 84 08 53, http://www.kdab.fr
KDAB - The Qt, C++ and OpenGL Experts
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20171005/f52df633/attachment.html>


More information about the Interest mailing list