C++ 基于Q3DScatter的自定义图表,QCustom3DItem运行缓慢

C++ 基于Q3DScatter的自定义图表,QCustom3DItem运行缓慢,c++,multithreading,qt,opengl,3d,C++,Multithreading,Qt,Opengl,3d,我想做一个带条形图的3D图表,条形图的颜色取决于它的大小。两者都很接近我要找的。最后,我基于Q3DScatter创建了一个图表,并添加了QCustom3DItem来绘制条形图,这样我就可以为每个项目设置网格项目和颜色。我在图表的每个位置都有一个项目。假设它是一个100x100的图表,意味着有10000条(自定义项) 我想每秒多次重画整个图表。我所说的重画是指每件物品都会改变大小和颜色。要设置项目大小,我调用。因为缩放是通过保持项目中心位置来工作的(我想保持条形基础位置),所以缩放后我必须立即调用

我想做一个带条形图的3D图表,条形图的颜色取决于它的大小。两者都很接近我要找的。最后,我基于
Q3DScatter
创建了一个图表,并添加了
QCustom3DItem
来绘制条形图,这样我就可以为每个项目设置网格项目和颜色。我在图表的每个位置都有一个项目。假设它是一个100x100的图表,意味着有10000条(自定义项)

我想每秒多次重画整个图表。我所说的重画是指每件物品都会改变大小和颜色。要设置项目大小,我调用。因为缩放是通过保持项目中心位置来工作的(我想保持条形基础位置),所以缩放后我必须立即调用。为了设定颜色,我打电话给你。因此,每秒调用多次类似以下get的代码:

for (int col = 0; col < 100; col++)
  for (int row = 0; row < 100; row++) {
    items[row*COLS+col]->setScalling(scale);
    items[row*COLS+col]->setPosition(position);
    items[row*COLS+col]->setTextureImage(image);
  }
main.cpp

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

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
图数据

class GraphData : public QObject {
    Q_OBJECT
    Q3DScatter* m_graph;
    QCustom3DItem* item;
public:
    explicit GraphData(Q3DScatter* m_graph);

public slots:
    void start();
    void setData(int scale);
};

#endif // GRAPHDATA_H
graphdata.cpp

#include "graphdata.h"

GraphData::GraphData(Q3DScatter* graph) : m_graph(graph){}

void GraphData::start() {
    item = new QCustom3DItem;
    item->setMeshFile(QStringLiteral(":mesh.obj"));
    m_graph->addCustomItem(item);
}

void GraphData::setData(int scale) {
//    item->setScaling();
}
网状qrc

<!DOCTYPE RCC><RCC version="1.0">
    <qresource>
        <file>mesh.obj</file>
    </qresource>
</RCC>
这看起来正在工作,
QCustom3DItem
位于另一个线程上,尽管存在警告:

QObject::setParent: Cannot set parent, new parent is in a different thread
我的理解是
m_graph->addCustomItem(item)
试图更改
item
父项,但失败了。我该如何处理这件事


我是否应该通过在另一个线程上处理自定义项来期望更好的性能?

Qt适用于原型设计或非性能关键代码。然而,它的面向对象方法与硬件的工作方式不一致,这使得编写高性能代码变得很困难

最好的方法是重写图形代码,以便在一次调用中渲染所有条形图。如果需要支持旧硬件,请使用所有顶点生成一个VBO,并在一个
glDrawArrays
调用中发送。如果最近的硬件还可以,那么您可以通过实例化和从纹理获取条高,在GPU上生成所有网格。在后一种情况下,每帧只需发送10000个浮点,这与带宽无关


一句话:实时渲染10000个立方体对于现代GPU来说是小菜一碟。Qt是你的瓶颈。

PosiTip:如果你改变立方体网格,所以原点(0,0,0)在它的底面中间,那么你就不需要调用<代码>设置位置< /代码>。
#include "graphdata.h"

GraphData::GraphData(Q3DScatter* graph) : m_graph(graph){}

void GraphData::start() {
    item = new QCustom3DItem;
    item->setMeshFile(QStringLiteral(":mesh.obj"));
    m_graph->addCustomItem(item);
}

void GraphData::setData(int scale) {
//    item->setScaling();
}
<!DOCTYPE RCC><RCC version="1.0">
    <qresource>
        <file>mesh.obj</file>
    </qresource>
</RCC>
# Blender v2.80 (sub 75) OBJ File: ''
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.375000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.875000 0.500000
vt 0.625000 0.500000
vt 0.625000 0.250000
vt 0.625000 0.750000
vt 0.625000 1.000000
vt 0.375000 0.750000
vt 0.875000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
s off
f 5/1/1 3/2/1 1/3/1
f 3/4/2 8/5/2 4/6/2
f 7/7/3 6/8/3 8/5/3
f 2/9/4 8/10/4 6/8/4
f 1/11/5 4/12/5 2/13/5
f 5/14/6 2/9/6 6/15/6
f 5/1/1 7/16/1 3/2/1
f 3/4/2 7/7/2 8/5/2
f 7/7/3 5/17/3 6/8/3
f 2/9/4 4/18/4 8/10/4
f 1/11/5 3/19/5 4/12/5
f 5/14/6 1/20/6 2/9/6
QObject::setParent: Cannot set parent, new parent is in a different thread