[Interest] Strange visibility problem after updating entities in Qt3D
Paul Lemire
paul.lemire at kdab.com
Thu Oct 5 11:46:05 CEST 2017
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= newQt3DRender::QRenderSettings();
auto* viewport= newQt3DRender::QViewport();
viewport->setNormalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f));
auto* renderSurfaceSelector=
newQt3DRender::QRenderSurfaceSelector(viewport);
auto* cameraSelector=
newQt3DRender::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= newQt3DRender::QClearBuffers(cameraSelector);
clearBuffer->setBuffers(Qt3DRender::QClearBuffers::ColorDepthStencilBuffer);
clearBuffer->setClearColor("#EEEEEE");
auto* layerFilterRails= newQt3DRender::QLayerFilter(clearBuffer);
layerFilterRails->addLayer(railsLayer);
// Branch 2 needs to render all entities with layer defectsLayer
auto* layerFilterDefects= newQt3DRender::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):
>
>
>
> voidRailEntityPrivate::initEntity()
>
> {
>
> Q_Q(RailEntity);
>
> auto* renderSettings= newQt3DRender::QRenderSettings();
>
> auto* viewport= newQt3DRender::QViewport();
>
> viewport->setNormalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f));
>
> auto* renderSurfaceSelector=
> newQt3DRender::QRenderSurfaceSelector(viewport);
>
> auto* layerFilter= newQt3DRender::QLayerFilter(renderSurfaceSelector);
>
> layerFilter->setEnabled(false);
>
> auto* cameraSelector= newQt3DRender::QCameraSelector(layerFilter);
>
> cameraSelector->setCamera(camera);
>
>
>
> auto* clearBuffer= newQt3DRender::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);
>
> autocamController= newQt3DExtras::QOrbitCameraController(q);
>
> camController->setLinearSpeed(300.0f);
>
> camController->setLookSpeed(180.0f);
>
> camController->setCamera(camera);
>
>
> renderSettings->pickingSettings()->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking);
>
> autoobjectPicker= newQt3DRender::QObjectPicker(q);
>
> q->addComponent(objectPicker);
>
> QObject::connect(objectPicker,
> &Qt3DRender::QObjectPicker::clicked, q, &RailEntity::onClicked);
>
> railParts= newQt3DCore::QEntity(q);
>
> railDefects= newQt3DCore::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:
>
>
>
> voiddeleteChildrenRecursively(constQt3DCore::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 | 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/53e1be55/attachment.html>
More information about the Interest
mailing list