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.muel...@gmail.com>; interest@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.lem...@kdab.com <mailto:paul.lem...@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
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest