openGLobj->Arrow メソッドをどのように実装したかについては指摘していませんが、これに 100% の CPU 時間を使用している場合は、おそらく即時モードで矢印をペイントしています。これは、glBegin() と glEnd() 内のすべての単一の命令で CPU から GPU にデータを転送する必要があるため、実際に CPU に負荷がかかります。GLUT を使用してデータを描画している場合、それも非常に非効率的です。
ここに行く方法は、GPU メモリと処理能力を使用してデータを表示することです。Phyatt は既にいくつかの指示を示していますが、より具体的に説明しようとします。Vertex Buffer Object (VBO)を使用します。
アイデアは、GPU でデータを表示するために必要なメモリを事前に割り当て、必要なときにこのメモリのチャンクを更新することです。CPU から GPU への転送を処理するために効率的なビデオ カード ドライバーを使用するため、これはおそらくコードの効率に大きな違いをもたらすでしょう。
概念を説明するために、回答の最後に疑似コードをいくつか示しますが、それは決して完全に正しいわけではありません。私はそれをテストしておらず、あなたのために図面を実装する時間がありませんでしたが、それはあなたの心を明確にすることができる概念です.
class Form
{
public:
Form()
{
// generate a new VBO and get the associated ID
glGenBuffers(1, &vboId);
// bind VBO in order to use
glBindBuffer(GL_ARRAY_BUFFER, vboId);
//Populate the buffer vertices.
generateVertices();
// upload data to VBO
glBufferData(GL_ARRAY_BUFFER_ARB, vertices.size(), vertices.data(), GL_STATIC_DRAW_ARB);
}
~Form()
{
// it is safe to delete after copying data to VBO
delete [] vertices;
// delete VBO when program terminated
glDeleteBuffersARB(1, &vboId);
}
//Implementing as virtual, because if you reimplement it on the child class, it will call the child method :)
//Generally you will not need to reimplement this class
virtual void draw()
{
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
//I am drawing the form as triangles, maybe you want to do it in your own way. Do it as you need! :)
//Look! I am not using glBegin() and glEnd(), I am letting the video card driver handle the CPU->GPU
//transfer in a single instruction!
glDrawElements(GL_TRIANGLES, vertices.size(), GL_UNSIGNED_BYTE, 0);
glDisableClientState(GL_VERTEX_ARRAY);
// bind with 0, so, switch back to normal pointer operation
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
private:
//Populate the vertices vector with the form vertices.
//Remember, any geometric form in OpenGL is rendered as primitives (points, quads, triangles, etc).
//The common way of rendering this is to use multiple triangles.
//You can draw it using glBegin() and glEnd() just to debug. After that, instead of rendering the triangles, just put
//the generated vertices inside the vertices buffer.
//Consider that it's at origin. You can use push's and pop's to apply transformations to the form.
//Each form(cone or cilinder) will have its own way of drawing.
virtual void generateVertices() = 0;
GLuint vboId;
std::vector<GLfloat> vertices;
}
class Cone : public Form
{
public:
Cone() : Form() {}
~Cone() : ~Form() {}
private:
void generateVertices()
{
//Populate the vertices with cone's formula. Good exercise :)
//Reference: http://mathworld.wolfram.com/Cone.html
}
GLuint vboId;
std::vector<GLfloat> vertices;
}
class Cilinder : public Form
{
public:
Cone() : Form() {}
~Cone() : ~Form() {}
private:
void generateVertices()
{
//Populate the vertices with cilinders's formula. Good exercise :)
//Reference: http://math.about.com/od/formulas/ss/surfaceareavol_3.htm
}
GLuint vboId;
std::vector<GLfloat> vertices;
}
class Visualizer : public QOpenGLWidget
{
public:
//Reimplement the draw function to draw each arrow for each data using the classes below.
void updateGL()
{
for(uint i = 0; i<data.size(); i++)
{
//I really don't have a clue on how you position your arrows around your world model.
//Keep in mind that those functions glPush, glPop and glMatrix are deprecated. I recommend you reading
//http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-3:-3D-transformation-and-projection.html if you want to implement this in the most efficient way.
glPush();
glMatrix(data[i].transform());
cilinder.draw();
cone.draw();
glPop();
}
}
private:
Cone cone;
Cilinder cilinder;
std::vector<Data> data;
}
最後に、これが最も効率的な方法であるとは断言できません。おそらく、大量のデータがある場合、コードを最適化するために、オクトリーやシーングラフなどのデータ構造が必要になるでしょう。
OpenSceneGraphまたはVisualization ToolKitを調べて、そのメソッドがまだ実装されていないかどうかを確認することをお勧めします。これにより、多くの時間を節約できます。