[Interest] Strange visibility problem after updating entities in Qt3D

Paul Lemire paul.lemire at kdab.com
Wed Oct 4 07:04:57 CEST 2017


Hi Helmut,

I've added my replies inline below.

Hopefully that might help.

Paul


On 10/03/2017 05:20 PM, Helmut Mülner wrote:
>
> Background:
>
> ==========
>
>    I have a QML application with big parts written in C++ (mostly
> models) that are exposed to QML with setContextProperty.
>
>  
>
>   I also have a 3DScene in QML:
>
>  
>
> Scene3D{
>
>     id:/scene3d/
>
>     width:4
>
>     focus:true
>
>     aspects:["input","logic"]
>
>     cameraAspectRatioMode:Scene3D.AutomaticAspectRatio
>
>     enabled:/visible/
>
>     visible:false
>
>     entity:controller.railViewer
>
> }
>
>  
>
> Step 1:
>
> =====
>
> railViewer is a pointer to a class derived from Qt3DCore::QEntity.
>
> It displays a part of a rail with special markers for “defects”.
>
> There is a “current defect” that is highlighted.
>
> My entity has the following childs (I gave “my” entities an objectName):
>
> Qt3DRender::QRenderSettings  
>
> Qt3DExtras::QOrbitCameraController  
>
> Qt3DRender::QObjectPicker  
>
> Qt3DInput::QInputSettings  
>
> Qt3DCore::QEntity   RailPart-0
>
> Qt3DCore::QEntity   RailPart-1
>
> Qt3DCore::QEntity   RailPart-2
>
> Qt3DCore::QEntity   RailPart-3
>
> Qt3DCore::QEntity   RailPart-4
>
> Qt3DCore::QEntity   RailPart-5
>
> Qt3DCore::QEntity   RailPart-6
>
> Qt3DCore::QEntity   RailPart-7
>
> DefectBoxEntity   RailDefect-1501
>
> set alpha to  0.95 for  0
>
> DefectBoxEntity   RailDefect-1502
>
> set alpha to  0.4 for  1
>
> (see rail1.jpg).
>
> The 3D view works like a charm.
>
>  
>
>  
>
> Step 2:
>
> =====
>
>  
>
> 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.
>
> My childs now are:
>
> Qt3DRender::QRenderSettings  
>
> Qt3DExtras::QOrbitCameraController  
>
> Qt3DRender::QObjectPicker  
>
> Qt3DInput::QInputSettings  
>
> Qt3DCore::QEntity   RailPart-0
>
> Qt3DCore::QEntity   RailPart-1
>
> Qt3DCore::QEntity   RailPart-2
>
> Qt3DCore::QEntity   RailPart-3
>
> Qt3DCore::QEntity   RailPart-4
>
> Qt3DCore::QEntity   RailPart-5
>
> Qt3DCore::QEntity   RailPart-6
>
> Qt3DCore::QEntity   RailPart-7
>
> DefectBoxEntity   RailDefect-501
>
> set alpha to  0.95 for  0
>
> DefectBoxEntity   RailDefect-502
>
> set alpha to  0.4 for  1
>
> DefectBoxEntity   RailDefect-503
>
> set alpha to  0.4 for  2
>
> DefectBoxEntity   RailDefect-504
>
> set alpha to  0.4 for  3
>
> DefectBoxEntity   RailDefect-505
>
> set alpha to  0.4 for  4
>
> DefectBoxEntity   RailDefect-506
>
> set alpha to  0.4 for  5
>
> DefectBoxEntity   RailDefect-507
>
> set alpha to  0.4 for  6
>
> DefectBoxEntity   RailDefect-508
>
> set alpha to  0.4 for  7
>
Did you specify a custom FrameGraph in QRenderSettings?
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.
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.

>  
>
> 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.
>
>         if(entity) {
>
>             autocomps= entity->components();
>
>             entity->setParent(nullParent);
>
>             for(auto* component: comps) {
>
>                 component->setParent(nullParent);
>
>                 entity->removeComponent(component);
>
>                 deletecomponent;
>
>             }
>
>         }
>
>         deleteChildrenRecursively(node->childNodes());
>
>         deletenode;
>
>     }
>
> }
>
>  
>
> voidRailEntityPrivate::load(doubleframeHeight,
> conststd::/vector/<std::pair<int, RealPointVector>>& finalPointVecs)
>
> {
>
>     Q_Q(RailEntity);
>
>     Qt3DCore::QNode* nullParent= nullptr;
>
>     qDebug() <<"RailEntityPrivate::load:";
>
>     autochilds= q->childNodes();
>
>     for(auto& node: childs) {
>
>         qDebug() <<node->metaObject()->className() <<"
> "<<qPrintable(node->objectName());
>
>     }
>
>     qDebug() <<"";
>
>     Qt3DCore::QNodeVectorrailNodes;
>
>     length= frameHeight* 3.0;
>
>     railNodes.reserve(childs.size());
>
>     for(auto* node: childs) {
>
>         if(node->objectName().startsWith(QLatin1String("Rail"))) {
>
>             railNodes.push_back(node);
>
>         }
>
>     }
>
>     for(auto* node: railNodes) {
>
>         Qt3DCore::QEntity* entity= (Qt3DCore::QEntity*)node;
>
>         entity->setParent(nullParent);
>
>         autoec= node->childNodes();
>
>         deleteChildrenRecursively(ec);
>
>         deleteentity;
>
>     }
>
>  
>
>     currentDefectIndex= -1;
>
>     computeExtend(finalPointVecs);
>
>     /size_t/startList= 0u;
>
>     /size_t/endList= finalPointVecs.size();
>
>     for(autoi= startList; i< endList; ++i) {
>
>         autoentity= newQt3DCore::QEntity(q);
>
>         entity->setObjectName(QStringLiteral("RailPart-")
> +QString::number(i));
>
>         autoflength= static_cast<float>(length);
>
>         automesh= newRailGeometryRenderer(finalPointVecs[i].second,
> flength);
>
>         automaterial= newQt3DExtras::QNormalDiffuseMapMaterial();
>
>         material->setShininess(10.0f);
>
>         material->setAmbient(QColor(76, 84, 76));
>
>         material->setSpecular(QColor(20, 20, 20));
>
>         autoseed= static_cast<unsignedint>(currentFrameNr* 100u + i);
>
>         autoheightMap= RailEntityPrivate::createRandomHeightMap(1024,
> 512, seed);
>
>         auto* diffuseImage= newMyTextureImage(heightMap);
>
>         material->diffuse()->addTextureImage(diffuseImage);
>
>         autonormalMap=
> RailEntityPrivate::makeNormalMapFromHeightMap(heightMap);
>
>         auto* normalImage= newMyTextureImage(normalMap);
>
>         material->normal()->addTextureImage(normalImage);
>
>         entity->addComponent(mesh);
>
>         entity->addComponent(material);
>
>     }
>
>     centerCamera();
>
> }
>
> voidRailEntity::updateDefects(constDefects& defects)
>
> {
>
>     Q_D(RailEntity);
>
>     /size_t/defectCount= defects./size/();
>
>     /size_t/index= 0;
>
>     autochilds= childNodes();
>
>     Qt3DCore::QNode* nullParent= nullptr;
>
>     qDebug() <<"RailEntity::updateDefects:";
>
>     for(auto& node: childs) {
>
>         qDebug() <<node->metaObject()->className() <<"
> "<<qPrintable(node->objectName());
>
>     }
>
>     qDebug() <<"";
>
>     Qt3DCore::QNodeVectorrailDefectNodes;
>
>     railDefectNodes.reserve(childs.size());
>
>     for(auto* node: childs) {
>
>         if(node->objectName().startsWith(QLatin1String("RailDefect-"))) {
>
>             railDefectNodes.push_back(node);
>
>         }
>
>     }
>
>     for(auto* node: railDefectNodes) {
>
>         Qt3DCore::QEntity* entity= (Qt3DCore::QEntity*)node;
>
>         entity->setParent(nullParent);
>
>         autoec= node->childNodes();
>
>         deleteChildrenRecursively(ec);
>
>         deleteentity;
>
>     }
>
>     for(constauto& defect: defects) {
>
>         QStringname= QLatin1String("RailDefect-")
> +QString::number(defect.id);
>
>         d->insertDefect(name, defect, this);
>
>     }
>
> }
>
> voidRailEntityPrivate::insertDefect(QStringname, constDefect& defect,
> Qt3DCore::QEntity* parent)
>
> {
>
>     QStringclassColor;
>
>     if(defectClassModel) {
>
>        
> classColor=defectClassModel->getColor(static_cast<int>(defect.classId));
>
>     }
>
>     QColorcol= classColor.isEmpty() ? QColor(128, 40, 0) :
> QColor(classColor);
>
>     autoentity= newDefectBoxEntity(defect, col, startMM, parent);
>
>     entity->setObjectName(name);
>
> }
>
>  
>
>  
>
> DefectBoxEntity has a transform, a base QPhongAlphaMaterial and 12
> QCuboidMeshes with associated transforms and using the base material.
>
>  
>
>  
>
> I suspect that either I do something wrong when I delete the “old”
> entities or there is a general synchronization problem with the
> rendering backend.
>
>  
>
> Anybody with ideas or suggestions?
>
>  
>
> Best regards,
>
> Helmut
>
>  
>
>  
>
>  
>
>  
>
>  
>
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest

-- 
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/20171004/a0e37fdf/attachment.html>


More information about the Interest mailing list