adding Qt3DCore::QEntity to q3dwindow dynamic(push a button to call slots in q3dwindow) cause transform odd.



  • we create 3d object like this in qt5.8-windows:

    //build a sphere
    m_sphereMesh = new Qt3DExtras::QSphereMesh(m_pRootEntity);
    m_mainSphereTransfrom = new Qt3DCore::QTransform(m_pRootEntity);
    m_mainSphereMaterial = new Qt3DExtras::QPhongMaterial(m_pRootEntity);

    //add component to sphere
    Qt3DCore::QEntity *mainEntity = new Qt3DCore::QEntity(m_pRootEntity);
    mainEntity->addComponent(m_sphereMesh);
    mainEntity->addComponent(m_mainSphereMaterial);
    mainEntity->addComponent(m_mainSphereTransfrom);

    everything goes well when we do all these(build all spheres) in initial time. but when we add a button to add another sphere during running time, this new build sphere act unnormal for move command like (m_newSphereTransfrom->setTranslation(m_posNewPos);)

    but the sphere display normal like pick, set color, or scale. only cannot move or rotate as initial-time build spheres.

    ===================================
    follow are all the source code, when your press the closer button, you will find that new sphere would not moved, but the position return by transform is changed.
    ===================================

    test3d.pro

    QT += core gui 3dcore 3drender 3dextras

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    TARGET = test3d
    TEMPLATE = app

    SOURCES += main.cpp
    window3d.cpp
    widget3d.cpp

    HEADERS += window3d.h
    widget3d.h

    main.cpp

    #include <QApplication>
    #include "widget3d.h"

    int main(int argc, char *argv[])
    {

    QApplication a(argc, argv);
    
    Widget3D mainWidget;
    mainWidget.show();
    
    return a.exec();
    

    }

    window3d.h

    #ifndef WINDOW3D_H
    #define WINDOW3D_H

    #include <Qt3DExtras/Qt3DWindow>
    #include <Qt3DCore>
    #include <Qt3DExtras/qphongmaterial.h>
    #include <QPickEvent>
    #include <QmouseEvent>
    #include <Qt3DExtras/qcylindermesh.h>
    #include <Qt3DExtras/qspheremesh.h>

    class Window3D : public Qt3DExtras::Qt3DWindow
    {
    Q_OBJECT

    public:

    Window3D(QObject *parent = 0);
    ~Window3D();
    
    void install3dEnvironment();
    
    void createSphere();
    

    public slots:

    void createNewSphere();
    void beCloser();
    

    protected:

    void addDirectLight(const QVector3D & pos, const QVector3D & dir, float intensity);
    

    private:

    Qt3DCore::QEntity *m_pRootEntity;
    Qt3DCore::QEntity * m_sphere;
    Qt3DExtras::QSphereMesh *m_mesh;
    Qt3DExtras::QPhongMaterial *m_material;
    Qt3DCore::QTransform *m_transfrom;
    
    Qt3DCore::QEntity * m_newSphere;
    Qt3DExtras::QSphereMesh *m_newMesh;
    Qt3DExtras::QPhongMaterial *m_newMaterial;
    Qt3DCore::QTransform *m_newTransfrom;
    

    };

    #endif // WINDOW3D_H

    window3d.cpp

    #include "window3d.h"
    #include <Qt3DRender/QDirectionalLight>
    #include <Qt3DRender/QCamera>
    #include <Qt3DRender/QCameraLens>
    #include <QOrbitCameraController>

    Window3D::Window3D(QObject *parent):
    m_pRootEntity(0),
    m_sphere(0),
    m_mesh(0),
    m_material(0),
    m_transfrom(0),
    m_newSphere(0),
    m_newMesh(0),
    m_newMaterial(0),
    m_newTransfrom(0)
    {

    m_pRootEntity = new Qt3DCore::QEntity();
    setRootEntity(m_pRootEntity);
    install3dEnvironment();
    createSphere();
    

    }

    Window3D::~Window3D()
    {

    }

    void Window3D::addDirectLight(const QVector3D & pos, const QVector3D & dir, float intensity)
    {

    Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(m_pRootEntity);
    Qt3DRender::QDirectionalLight *light = new Qt3DRender::QDirectionalLight(m_pRootEntity);
    light->setColor("white");
    light->setIntensity(intensity);
    light->setWorldDirection(dir);
    Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(m_pRootEntity);
    lightTransform->setTranslation(pos);
    lightEntity->addComponent(light);
    lightEntity->addComponent(lightTransform);
    

    }

    void Window3D::install3dEnvironment()
    {

    Qt3DRender::QCamera *cameraEntity = camera();
    cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 100.0f);
    cameraEntity->setPosition(QVector3D(0, 0, 20));
    cameraEntity->setUpVector(QVector3D(0, 1, 0));
    cameraEntity->setViewCenter(QVector3D(0, 0, 0));
    
    addDirectLight(QVector3D(0, 0, 20), QVector3D(0, 0, -20), 1);
    
    Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(m_pRootEntity);
    camController->setCamera(cameraEntity);
    

    }

    void Window3D::createSphere()
    {

    m_mesh = new Qt3DExtras::QSphereMesh(m_pRootEntity);
    m_mesh->setRings(20);
    m_mesh->setSlices(50);
    m_mesh->setRadius(1);
    
    m_transfrom = new Qt3DCore::QTransform(m_pRootEntity);
    m_transfrom->setTranslation(QVector3D(-4,0,0));//set position
    
    m_material = new Qt3DExtras::QPhongMaterial(m_pRootEntity);
    m_material->setDiffuse("yellow");
    
    m_sphere = new Qt3DCore::QEntity(m_pRootEntity);
    m_sphere->addComponent(m_mesh);
    m_sphere->addComponent(m_transfrom);
    m_sphere->addComponent(m_material);
    

    }

    void Window3D::createNewSphere()
    {

    if (m_newSphere) return;
    m_newMesh = new Qt3DExtras::QSphereMesh(m_pRootEntity);
    m_newMesh->setRings(20);
    m_newMesh->setSlices(50);
    m_newMesh->setRadius(2);
    
    m_newTransfrom = new Qt3DCore::QTransform(m_pRootEntity);
    m_newTransfrom->setTranslation(QVector3D(4,0,0));//set position
    
    m_newMaterial = new Qt3DExtras::QPhongMaterial(m_pRootEntity);
    m_newMaterial->setDiffuse("green");
    
    m_newSphere = new Qt3DCore::QEntity(m_pRootEntity);
    m_newSphere->addComponent(m_newMesh);
    m_newSphere->addComponent(m_newTransfrom);
    m_newSphere->addComponent(m_newMaterial);
    

    }

    void Window3D::beCloser()
    {

    if (m_newSphere && m_sphere)
    {
        m_transfrom->setTranslation(m_transfrom->translation()+QVector3D(0.1,0,0));
        m_newTransfrom->setTranslation(m_newTransfrom->translation() + QVector3D(-0.2, 0, 0));
    
        qDebug() << "new position:" << m_transfrom->translation() << m_newTransfrom->translation();
    }
    

    }

    widget3d.h

    #ifndef WIDGET3D_H
    #define WIDGET3D_H

    #include "window3d.h"
    #include <QWidget>

    class Widget3D : public QWidget
    {
    Q_OBJECT

    public:

    Widget3D(QObject *parent = 0);
    ~Widget3D();
    

    private:

    Window3D * m_wind3d;
    

    };

    #endif // WIDGET3D_H

    widget3d.cpp

    #include "widget3d.h"
    #include <QPushButton>
    #include <QHBoxLayout>

    Widget3D::Widget3D(QObject *parent)
    {

    m_wind3d = new Window3D();
    QWidget *view3d = QWidget::createWindowContainer(m_wind3d,this);
    QSize screenSize = m_wind3d->screen()->size();
    view3d->setMinimumSize(QSize(800, 500));
    view3d->setMaximumSize(screenSize);
    
    QHBoxLayout *hLayout = new QHBoxLayout(this);
    QVBoxLayout *vLayout = new QVBoxLayout(this);
    
    hLayout->addWidget(view3d);
    hLayout->addLayout(vLayout);
    
    
    QPushButton *addNewSphere = new QPushButton(this);
    addNewSphere->setText(tr("New Sphere"));
    connect(addNewSphere, SIGNAL(clicked()), m_wind3d, SLOT(createNewSphere()));
    vLayout->addWidget(addNewSphere);
    
    QPushButton *closerSphere = new QPushButton(this);
    closerSphere->setText(tr("Be Closer"));
    connect(closerSphere, SIGNAL(clicked()), m_wind3d, SLOT(beCloser()));
    vLayout->addWidget(closerSphere);
    
    this->setLayout(hLayout);
    

    }

    Widget3D::~Widget3D()
    {

    }



  • Hi,

    you may need to update() the Qt3DWindow explicitly.

    -Michael.



  • @m.sue I have tried Qt3DWindow::requestUpdate() after building sphere but it makes no diffrence. Also I call it in the timer, it keeps the same.
    Any other advices?



  • Hi,

    please show how you create the second sphere, the "set translation" functions and how you call it.

    -Michael.



  • @m.sue the creation are the same. like this:
    Qt3DCore::QTransform *localTransform = new Qt3DCore::QTransform(m_pRootEntity);
    localTransform->setTranslation(pt3d);
    m_vecSphereTransform.append(localTransform);

    Qt3DExtras::QPhongMaterial *localMaterial = new Qt3DExtras::QPhongMaterial(m_pRootEntity);
    localMaterial->setDiffuse(m_colorSphere);
    m_vecSphereMaterial.append(localMaterial);

    Qt3DCore::QEntity *localEntity = new Qt3DCore::QEntity(m_pRootEntity);

    localEntity->addComponent(m_sphereMesh);
    localEntity->addComponent(localMaterial);
    localEntity->addComponent(localTransform);
    m_vecSpheres.push_back(localEntity);

    we save the pointer to QTransform into a vector and operate the position with the pointer in a timer.



  • Hi,

    I see two difference to how I do it:

    • I do not set the root entity as parent to the mesh, material nor transform.
    • I create a new mesh for each sphere.

    Hope that helps.

    -Michael.



  • @m.sue I remove the root entity as parent to the mesh, material nor transform. it really works, thanks very much....
    but I do not know why it acts like that way.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.