Ok.. I wanted to see how far this could go.. and implemented a low-level GL solution. It's a bit messy.. just wanted to check it out. Prerendering the sequences to big display lists doesn't give a speed boost and introduces problems with empty displaylists, if the gl context runs out of memory (?).

That's as far as brute force optimization goes, I think. Further optimizations can be achieved by only drawing the visible items or rendering a big pixmap if the detail level drops to a resolution that can be handled. Both together should allow for a smooth user interaction. To see what items are to be drawn you could look into glUnproject.

Qt Code:
  1. #ifndef MAINGL_H
  2. #define MAINGL_H
  3.  
  4. #include <QtOpenGL>
  5.  
  6. class MainWindow : public QGLWidget
  7. { Q_OBJECT
  8. public:
  9. MainWindow(QWidget *parent = 0,int seq_length = 5000,int num_seq = 80) : QGLWidget(parent)
  10. {
  11. // generate random data to display
  12. data.reserve(num_seq);
  13. QVector<quint8> seq0;
  14. seq0.reserve(seq_length);
  15. for(int j=0;j<seq_length;j++)
  16. {
  17. seq0.push_back( int(rand()/float(RAND_MAX)*4) );
  18. }
  19. data.push_back(seq0);
  20.  
  21. for(int i=1;i<num_seq;i++)
  22. {
  23. QVector<quint8> seq_i;
  24. seq_i.reserve(seq_length);
  25. for(int j=0;j<seq_length;j++)
  26. {
  27. if(rand()/float(RAND_MAX)*20 < 1)
  28. seq_i.push_back( int(rand()/float(RAND_MAX)*4) );
  29. else
  30. seq_i.push_back( data.at(0).at(j) );
  31. }
  32. data.push_back(seq_i);
  33. }
  34. camPos[0] = 0;camPos[1] = num_seq*10;camPos[2] = 2000;
  35. totaldisplaylist = 0;
  36. totaldisplaylistcount = 0;
  37. gldisplist = 0;
  38. }
  39. ~MainWindow()
  40. {
  41. for (quint8 i=0;i < 4;++i) deleteTexture(gltextures[i]);
  42. if (totaldisplaylist) glDeleteLists(totaldisplaylist,totaldisplaylistcount);
  43. if (gldisplist) glDeleteLists(gldisplist,4);
  44. }
  45.  
  46. protected:
  47.  
  48. void initializeGL()
  49. {
  50. // Set up the rendering context, define display lists etc.:
  51. glClearColor(1.0, 1.0, 1.0, 1.0);
  52. glEnable(GL_TEXTURE_2D);
  53. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  54.  
  55. QString alpha = "ACGT";
  56. QColor tile_colors[] = { QColor("blue"), QColor("green"), QColor("yellow"), QColor("red") };
  57. // Generate 4 consecutive displaylists
  58. gldisplist = glGenLists(4);
  59. // Prepare 4 textures
  60. for (quint8 i=0;i < 4;++i)
  61. {
  62. QChar base_char = alpha.at(i);
  63. QColor color = tile_colors[i];
  64. QPixmap* pmap = new QPixmap(20,20);
  65. textures[i] = pmap;
  66. QPainter painter(pmap);
  67. painter.fillRect(QRectF(0, 0, 20, 20), color);
  68. painter.setFont(QFont("Times",10));
  69. painter.setPen(QColor("black"));
  70. painter.drawText(0, 0, 20, 20,0x0084, QString(base_char));
  71. gltextures[i] = bindTexture(*pmap);
  72. qDebug() << gltextures[i];
  73.  
  74. // compile display list
  75. glNewList(gldisplist+i, GL_COMPILE);
  76. {
  77. glBindTexture(GL_TEXTURE_2D, gltextures[i]);
  78.  
  79. glBegin(GL_QUADS);
  80.  
  81. // Upper right corner
  82. glTexCoord2f(0.0, 1.0);
  83. glVertex3f(0.0, 20, 0.0);
  84.  
  85. // Upper right corner
  86. glTexCoord2f(1.0, 1.0);
  87. glVertex3f(20, 20, 0.0);
  88.  
  89. // Lower right corner
  90. glTexCoord2f(1.0, 0.0);
  91. glVertex3f(20, 0.0, 0.0);
  92.  
  93. // Lower left corner
  94. glTexCoord2f(0.0, 0.0);
  95. glVertex3f(0.0, 0.0, 0.0);
  96. glEnd();
  97. }
  98. glEndList();
  99. }
  100. prerender = false;
  101. if (prerender)
  102. renderGL();
  103. }
  104.  
  105. void resizeGL(int w, int h)
  106. {
  107. // setup viewport, projection etc.:
  108. glMatrixMode(GL_PROJECTION);
  109. glLoadIdentity();
  110. glViewport(0, 0, (GLint)w, (GLint)h);
  111. gluPerspective(70.0, (float)w/(float)h, 0.01f, 100000.0f);
  112. //glOrtho(1,w,1,h,-1,10);
  113. }
  114.  
  115. void renderGL()
  116. {
  117. if (totaldisplaylist) glDeleteLists(totaldisplaylist,totaldisplaylistcount);
  118. totaldisplaylistcount = data.size();
  119. totaldisplaylist = glGenLists(totaldisplaylistcount);
  120. float x_inc = 20;
  121. float y_inc = 20;
  122. for (int i = 0; i < data.size(); i++)
  123. {
  124. glNewList(totaldisplaylist+i, GL_COMPILE);
  125. {
  126. QVector<quint8> seq = data.at(i);
  127. for (int j = 0; j < seq.size(); j++)
  128. {
  129. glCallList(gldisplist+seq.at(j));
  130. glTranslatef(20,0,0);
  131. }
  132. glTranslatef(-x_inc*seq.size(),y_inc,0);
  133. }
  134. glEndList();
  135. }
  136. }
  137.  
  138. void paintGL()
  139. {
  140. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  141. glMatrixMode(GL_MODELVIEW);
  142. glLoadIdentity();
  143. // Setup camera ..
  144. gluLookAt(camPos[0],camPos[1],camPos[2],camPos[0],camPos[1],camPos[2]-500,0,1,0);
  145. if (prerender) {
  146. // draw the scene:
  147. for (int i = 0; i < data.size(); i++)
  148. {
  149. glCallList(totaldisplaylist+i);
  150. }
  151. } else {
  152. float x_inc = 20;
  153. float y_inc = 20;
  154. for (int i = 0; i < data.size(); i++)
  155. {
  156. QVector<quint8> seq = data.at(i);
  157. for (int j = 0; j < seq.size(); j++)
  158. {
  159. glCallList(gldisplist+seq.at(j));
  160. glTranslatef(20,0,0);
  161. }
  162. glTranslatef(-x_inc*seq.size(),y_inc,0);
  163. }
  164. }
  165. }
  166.  
  167. void keyPressEvent(QKeyEvent *event)
  168. {
  169. // CAMERA
  170. if ((event->modifiers() == Qt::NoModifier) || (event->modifiers() == Qt::ShiftModifier))
  171. {
  172. qreal delta = 50;
  173. if (event->modifiers() == Qt::ShiftModifier) delta *= 10;
  174. switch (event->key()) {
  175. case Qt::Key_Left : {camPos[0] -= delta;}; break;
  176. case Qt::Key_A : {camPos[0] -= delta;}; break;
  177. case Qt::Key_Right : {camPos[0] += delta;}; break;
  178. case Qt::Key_D : {camPos[0] += delta;}; break;
  179. case Qt::Key_Down : {camPos[1] += delta;}; break;
  180. case Qt::Key_W : {camPos[1] += delta;}; break;
  181. case Qt::Key_Up : {camPos[1] -= delta;}; break;
  182. case Qt::Key_S : {camPos[1] -= delta;}; break;
  183. case Qt::Key_Q : {camPos[2] -= delta;}; break;
  184. case Qt::Key_E : {camPos[2] += delta;}; break;
  185. }
  186. update();
  187. }
  188. }
  189. private:
  190. // The 4 characters
  191. QPixmap* textures[4];
  192. GLuint gltextures[4];
  193. GLuint gldisplist;
  194. // Each sequence as a displaylist
  195. GLuint totaldisplaylist;
  196. int totaldisplaylistcount;
  197. float camPos[3];
  198. bool prerender;
  199. QVector< QVector<quint8> > data;
  200. };
  201.  
  202. #endif // MAINGL_H
  203.  
  204. -------------------------------
  205.  
  206. #include <QtCore>
  207. #include <QtGui>
  208.  
  209. #include "maingl.h"
  210.  
  211. int main(int argc, char *argv[])
  212. {
  213. QApplication a(argc, argv);
  214.  
  215. MainWindow w;
  216. w.show();
  217. return a.exec();
  218. }
To copy to clipboard, switch view to plain text mode 
Hope it helps!

Johannes