Qt3D: QGLMaterial / QGLMaterialCollection: large scene about 1000 Objects + 1000 QGLMaterials



  • I use Qt3D for my thesis. The scene consists of the 1500 spheres and 1000 the cylinders. The different color must be set for each sphere and cylinder. I use a QGLCollectionMaterial, create n of QGLMaterial-Object and add material to Collection. For each QGLSceneNode (sphere or cylinder) i set a palette - MaterialCollection and then call setMaterialIndex(i), where i is corresponding index. With n = 25 (Material count) and 2000 of QGLSceneNodes , the scene is rendered, but a little slow responding to the mouse manipulation (rotate, zoom). A further increase in number of colors is the scene even less interactive, and with n = 100 it looks like a slideshow. In my example, instead of the color QGLMaterial includes the texture, but that does not matter. The same happens if the color is set. I modified the example of qt3d/src/examples/qt3d/builder. Below is a source code:

    Header File:

    @#ifndef BUILDER_H
    #define BUILDER_H
    #include "qglview.h"

    QT_BEGIN_NAMESPACE
    class QGLSceneNode;
    class QGLBuilder;
    QT_END_NAMESPACE
    class BuilderView : public QGLView
    {
    Q_OBJECT
    public:
    BuilderView(const QGLFormat &f, QWidget *parent = 0);
    ~BuilderView();
    protected:
    void initializeGL(QGLPainter *painter);
    void paintGL(QGLPainter *painter);
    private:
    QGLSceneNode *buildGeometry();
    QGLSceneNode *buildGeometry2(qreal radius = 1.0, int divisions = 5);
    QGLSceneNode *canScene;
    int mCount;
    int mColorCount;
    QGLMaterialCollection *mPalette;
    void initializePalette();
    };
    #endif@

    Cpp-file:

    @#include "builder.h"
    #include "qglbuilder.h"
    #include "qglmaterialcollection.h"
    #include "qgltexture2d.h"
    #include "qglmaterial.h"
    #include "qglscenenode.h"
    #include "qgllightmodel.h"
    #include "qglsphere.h"
    #include "qglcylinder.h"
    #include <QtGui/qmatrix4x4.h>
    #include <QtCore/qmath.h>

    static inline qreal rval()
    {
    return qreal((qreal(qrand()) / qreal(RAND_MAX)) * 200.0);
    }

    static inline int ival()
    {
    return (qreal(qrand()) / qreal(RAND_MAX)) * 255;
    }

    BuilderView::BuilderView(const QGLFormat &f, QWidget *parent)
    : QGLView(f, parent)
    , canScene(new QGLSceneNode(this))
    {
    QGLSceneNode *can = buildGeometry();
    //QGLSceneNode *sphere = buildGeometry2();
    mPalette = new QGLMaterialCollection(canScene);
    mCount = 1000;
    mColorCount = 100;
    initializePalette();
    can->setObjectName("SceneNode Can");
    canScene->setObjectName("Root - canScene");
    for(int i = 1; i < mCount; i++)
    {
    QGLSceneNode *node = new QGLSceneNode(canScene);
    node->setObjectName("Sphere_r_" + QString::number(i));
    node->setPalette(mPalette);
    node->setMaterialIndex(i % mColorCount);;
    node->setEffect(QGL::LitModulateTexture2D);
    node->addNode(can);
    {
    QMatrix4x4 mat;
    mat.translate(1.0f * rval(), 1.0f * rval(), -1.0f * rval());
    node->setLocalTransform(mat);
    }
    node = new QGLSceneNode(canScene);
    node->setObjectName("Sphere_b_" + QString::number(i));
    node->setPalette(mPalette);
    node->setMaterialIndex(i % mColorCount);
    node->setEffect(QGL::LitModulateTexture2D);
    node->addNode(can);
    {
    QMatrix4x4 mat;
    mat.translate(-1.0f * rval(), -1.0f * rval(), -1.0f * rval());
    node->setLocalTransform(mat);
    }
    }
    }

    BuilderView::~BuilderView()
    {
    delete canScene;
    }

    void BuilderView::initializeGL(QGLPainter *painter)
    {
    glEnable(GL_CULL_FACE);
    camera()->setFieldOfView(45);
    camera()->setNearPlane(0.1);
    camera()->setFarPlane(5000);
    camera()->setEye(QVector3D(0.0, 0.0, 100.0));
    }

    void BuilderView::paintGL(QGLPainter *painter)
    {
    canScene->draw(painter);
    }

    QGLSceneNode *BuilderView::buildGeometry()
    {
    QGLBuilder builder;
    builder << QGLCylinder(1.0f, 1.0f, 5.0f, 32);
    return builder.finalizedSceneNode();
    }

    QGLSceneNode *BuilderView::buildGeometry2(qreal radius, int divisions)
    {
    QGLBuilder builder;
    builder << QGLSphere(radius, divisions);
    return builder.finalizedSceneNode();
    }

    void BuilderView::initializePalette()
    {
    for(int i = 0; i < mColorCount; i++)
    {
    QImage image(QSize(1, 6), QImage::Format_ARGB32_Premultiplied);
    QPainter painter(&image);
    QColor c(ival(), ival(), ival());
    QColor c2(ival(), ival(), ival());
    QLinearGradient linearGrad(QPointF(0.5, 0), QPointF(0.5, 6));
    linearGrad.setColorAt(0, c);
    linearGrad.setColorAt(1, c2);
    painter.fillRect(image.rect(), linearGrad);
    painter.end();
    QGLMaterial *m = new QGLMaterial;
    //m->setColor(c);
    QGLTexture2D *tex = new QGLTexture2D(m);
    tex->setImage(image);
    m->setTexture(tex);
    mPalette->addMaterial(m);
    }
    }@

    With a few manipulations can reproduce several cases: e.g. add color or texture to the material, change the number of objects, change the number of colors / materials, etc. The dependency that I have noticed is the number of materials in the collection + number of QGLScenenodes. I've done a few tests with the other example "tank" under qt3d/examples/qt3d. There the scene is less interactive with the number of tank-objects from 250-300. This case can you self produce with 200 times DoubleClick. )))

    Summary: is a bug in Qt3D or anybody have a ide, how to put or to manage a large amount of colors / materials for several QGLScenenodes. And under "several QGLScenenodes" i understand more than 2000 objects.

    My thesis software looks of course different, but the idea is the same. And maybe one preliminary question: if it is possible to use/set several colors to multiple objects in the scene, then I can change the color easily in runtime?


Log in to reply
 

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