--- /dev/null
+#include "PathScene.h"
+
+#include <QMouseEvent>
+#include <QRubberBand>
+#include <QRect>
+#include <iostream>
+
+#include <GL/gl.h>
+
+PathScene::PathScene(int frags, int len, QWidget *parent) :
+ QGLWidget(parent),
+ X(0),
+ clipZ(32.0),
+ zoom(0),
+ maxOrtho2d(-50.0, -50, 3000000.0, 300.0),
+ curOrtho2d(maxOrtho2d),
+ fragsize(frags),
+ length(len),
+ rubberBand(0),
+ debugBand(true),
+ drawingBand(false)
+{
+}
+
+QSize PathScene::sizeHint() const
+{
+ return QSize(400, 400);
+}
+
+void PathScene::setX(int newX)
+{
+ if (X != newX) {
+ X = newX;
+ update();
+ }
+}
+
+static float max(float a, float b)
+{
+ if ( a < b)
+ return b;
+ else
+ return a;
+}
+
+static float min(float a, float b)
+{
+ if ( a < b)
+ return a;
+ else
+ return b;
+}
+
+void PathScene::setZoom(int newZoom)
+{
+ std::cout << newZoom << " " << zoom << std::endl;
+ if (zoom != newZoom) {
+ // try to figure out where we should be now?
+
+ float width = maxOrtho2d.width();
+ std::cout << "max width " << width
+ << " max left " << maxOrtho2d.left()
+ << " max right " << maxOrtho2d.right() << std::endl;
+ float newWidth = width / newZoom;
+ std::cout << "new width" << newWidth<< std::endl;
+ float center = curOrtho2d.width()/2 + curOrtho2d.left();
+ std::cout << "l: " << curOrtho2d.left() << " r: " << curOrtho2d.right()
+ << " ctr: " << center << std::endl;
+ curOrtho2d.setLeft(max(center-newWidth, maxOrtho2d.left()));
+ curOrtho2d.setRight(min(center+newWidth, maxOrtho2d.right()));
+ std::cout << "nl: " << curOrtho2d.left() << " nr: " << curOrtho2d.right()
+ << std::endl;
+ zoom = newZoom;
+ update();
+ }
+}
+
+void PathScene::setClipPlane(int newZ)
+{
+ if (clipZ != (double) newZ){
+ clipZ = (double) newZ;
+ update();
+ }
+}
+
+void PathScene::initializeGL()
+{
+ glEnable(GL_DEPTH_TEST|GL_BLEND);
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glShadeModel(GL_FLAT);
+ glLoadIdentity();
+ glPushMatrix();
+}
+
+void PathScene::resizeGL(int width, int height)
+{
+ glViewport(0, 0, (GLsizei)width, (GLsizei)height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // I'm abusing this as Qt and OpenGL disagree about the direction of the
+ // y axis
+ glOrtho(curOrtho2d.left(), curOrtho2d.right(),
+ curOrtho2d.top(), curOrtho2d.bottom(),
+ -50.0, clipZ);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+void PathScene::paintGL()
+{
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(curOrtho2d.left(), curOrtho2d.right(),
+ curOrtho2d.top(), curOrtho2d.bottom(),
+ -50.0, clipZ);
+ glMatrixMode(GL_MODELVIEW);
+ if (debugBand && !drawingBand) {
+ glColor4f(0.4, 0.4, 0.4, 0.9);
+ glRectf(previousBand.x(), previousBand.y(),
+ previousBand.right(), previousBand.bottom());
+ }
+ glTranslatef(-X*1000, 0.0, 0.0);
+ mussaesque(fragsize, length);
+
+ glPopMatrix();
+ glFlush();
+}
+
+static void processHits(GLint hits, GLuint buffer[])
+{
+ GLuint names, *ptr;
+
+ std::cout << "hits = " << hits << std::endl;
+ ptr = (GLuint *) buffer;
+ for (GLint i=0; i < hits; ++i)
+ {
+ names = *ptr;
+ std::cout << " number of names for hit " << i << " " << names << std::endl;
+ ptr++;
+ std::cout << " z1 is " << (float) *ptr/0x7fffffff << std::endl;
+ ptr++;
+ std::cout << " z2 is " << (float) *ptr/0x7fffffff << std::endl;
+ ptr++;
+ std::cout << " the name is ";
+ for (GLuint j=0; j < names; j++)
+ {
+ std::cout << *ptr;
+ ptr++;
+ }
+ std::cout << std::endl;
+ }
+}
+
+void PathScene::mousePressEvent( QMouseEvent *e)
+{
+ drawingBand = true;
+ std::cout << "x=" << e->x() << " y=" << e->y() << std::endl;
+
+ bandOrigin = e->pos();
+ if (!rubberBand)
+ rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
+
+ rubberBand->setGeometry(QRect(bandOrigin, QSize()));
+ rubberBand->show();
+}
+
+void PathScene::mouseMoveEvent( QMouseEvent *e)
+{
+ rubberBand->setGeometry(QRect(bandOrigin, e->pos()).normalized());
+}
+
+void dumpRect(const QRect &r)
+{
+ std::cout << "x=" << r.x() << " y=" << r.y()
+ << " w=" << r.width() << " h=" << r.height() << std::endl;
+}
+
+void PathScene::mouseReleaseEvent( QMouseEvent *e)
+{
+ drawingBand = false;
+ rubberBand->hide();
+ QRect r = QRect(bandOrigin, e->pos()).normalized();
+ bandOrigin = r.topLeft();
+ std::cout << "band ";
+ dumpRect(r);
+
+ std::cout << "window ";
+ dumpRect(geometry());
+
+ GLfloat x_scale = curOrtho2d.width()/((float)geometry().width());
+ GLfloat y_scale = curOrtho2d.height()/((float)geometry().height());
+ GLfloat x_left = curOrtho2d.left() + (r.x()*x_scale);
+ GLfloat x_right = x_left + r.width() * x_scale;
+ // using QRectF with Y axis swapped
+ GLfloat y_top = curOrtho2d.bottom()-(r.y()*y_scale);
+ GLfloat y_bottom = y_top - r.height() * y_scale;
+ previousBand.setCoords(x_left, y_top, x_right, y_bottom);
+ std::cout << x_left << " " << x_right << " " << y_top << " " << y_bottom
+ << std::endl;
+
+ GLuint selectBuf[512];
+ glSelectBuffer(512, selectBuf);
+ GLint hits;
+
+ (void)glRenderMode(GL_SELECT);
+ glInitNames();
+ glPushName(42);
+ glPushMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(x_left, x_right, y_top, y_bottom, -50.0, 50.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ mussaesque(fragsize, length);
+ glFlush();
+
+ glPopMatrix();
+ hits = glRenderMode(GL_RENDER);
+ processHits(hits, selectBuf);
+
+ resizeGL(geometry().width(), geometry().height());
+}
+
+
+//////
+// openGl rendering code
+
+static void seq_track(long length, long height)
+{
+ glLineWidth(5);
+ glColor3f(0.9, 0.6, 0.9);
+ glBegin(GL_LINES);
+ glVertex3f(0.0, (GLfloat)height, -1.0);
+ glVertex3f((GLfloat)length, (GLfloat)height, -1.0);
+ glEnd();
+}
+
+static void tracks()
+{
+ glPushMatrix();
+ glLoadName(1);
+ seq_track(2000000, 0);
+ glLoadName(2);
+ seq_track(2500000, 100);
+ glLoadName(3);
+ seq_track(1900000, 200);
+ glPopMatrix();
+}
+
+static void draw_lines(int fragsize, int length)
+{
+ float depth = 1.0;
+
+ glColor3f(0.3, 0.9, 0.3);
+ glLineWidth(0.001);
+ GLfloat x;
+ GLfloat z;
+ const long short_sequence_len = 1800000;
+ long blocks = short_sequence_len / fragsize;
+ std::cout << "blocks " << blocks << std::endl;
+ std::cout << "line count " << blocks * length << std::endl;
+ for (long base_block=0; base_block < blocks; ++base_block)
+ {
+ for (long base_offset=0; base_offset < length; ++base_offset)
+ {
+ glBegin(GL_LINE_STRIP);
+ x = (GLfloat)(base_block * fragsize +base_offset);
+
+ depth -= 0.1;
+ if (depth < -2.0) depth = 1.0;
+
+ z = (-32.0 - (-32.0 * depth));
+
+ //std::cout << "Z: " << z << "\n";
+
+ glVertex3f(x, 0.0, z );
+ glVertex3f(x+200000.0, 100, z );
+ glVertex3f(x+100.0, 200, z );
+ glEnd();
+ }
+ }
+}
+
+static GLuint make_line_list(int fragsize, int length)
+{
+ GLuint line_list = glGenLists(1);
+ glNewList(line_list, GL_COMPILE);
+
+ draw_lines(fragsize, length);
+
+ glEndList();
+ return line_list;
+
+}
+
+void PathScene::mussaesque(int fragments, int length)
+{
+ static GLuint theLines = make_line_list(fragments, length);
+
+ glInitNames();
+ glPushName(0);
+ tracks();
+ glLoadName(10);
+ glCallList(theLines);
+ glPopName();
+ //draw_lines();
+}
+
+