#include "glvoxelview.h"
// OpenGL rendered voxel view
GLVoxelView::GLVoxelView( QWidget *parent, const char *name )
: QGLWidget( parent, name )
{
object = 0;
wire_object = 0;
point_object = 0;
voxelData = 0;
currentLayer = 0;
xAxisAngle = yAxisAngle = zAxisAngle = 0;
}
void GLVoxelView::setVoxelModel( VoxelData *data )
{
voxelData = data;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(-voxelData->width(), voxelData->height(), -voxelData->depth(),
voxelData->width(), -voxelData->height(), voxelData->depth());
glMatrixMode( GL_MODELVIEW );
updateGL();
}
void GLVoxelView::setViewAngles( int xAngle, int yAngle, int zAngle )
{
xAxisAngle = xAngle;
yAxisAngle = yAngle;
zAxisAngle = zAngle;
updateGL();
}
void GLVoxelView::setCurrentLayer( int layer )
{
currentLayer = layer;
updateGL();
}
void GLVoxelView::initializeGL()
{
qglClearColor( Qt::black );
glShadeModel( GL_FLAT );
glEnable( GL_CULL_FACE );
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
GLfloat specular [] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat shininess [] = { 90.0 };
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
GLfloat position [] = { 0.0, 1.0, -1.0, 0.0 };
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
object = makeObject();
wire_object = makeWireObject();
point_object = makePointObject();
}
void GLVoxelView::paintGL()
{
GLfloat scale = 1.0;
GLfloat xRot = xAxisAngle+90;
GLfloat yRot = yAxisAngle;
GLfloat zRot = zAxisAngle;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glRotatef( xRot, 1.0, 0.0, 0.0 );
glRotatef( yRot, 0.0, 1.0, 0.0 );
glRotatef( zRot, 0.0, 0.0, 1.0 );
glTranslatef( -voxelData->width()/2, -voxelData->height()/2, -voxelData->depth()/2 );
glScalef( scale, scale, scale );
qglColor( Qt::white );
glLineWidth( 2.0 );
glBegin( GL_LINES );
glVertex3f( 0, 0, 0 ); glVertex3f(voxelData->width(), 0, 0 );
glVertex3f( 0, 0, 0 ); glVertex3f(0, voxelData->height(), 0 );
glVertex3f( 0, 0, 0 ); glVertex3f(0, 0, voxelData->depth() );
glEnd();
if ( !voxelData )
return;
GLfloat trans [] = { 0.8, 0.8, 0.8, 0.1 };
glTranslatef( 0, voxelData->height(), 0 );
glTranslatef( 0, 0, voxelData->depth() );
for ( int z = voxelData->depth()-1; z >= 0; z-- ) {
QRgb **layer = voxelData->layer(z);
if ( z < currentLayer ) {
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, trans);
glEnable(GL_BLEND);
glDepthMask(GL_FALSE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);//_MINUS_SRC_ALPHA);
}
for ( int x = 0; x < voxelData->width(); x++ ) {
for ( int y = 0; y < voxelData->height(); y++ ) {
if ( layer[x][y] ) {
QRgb rgb = voxelData->colorOf( x, y, z, int(xRot-90), int(yRot), int(zRot) );
glColor4f( qRed(rgb)/255.0, qGreen(rgb)/255.0, qBlue(rgb)/255.0, 0.15 );
glCallList(object);
if (z == currentLayer) {
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glLineWidth(1.5);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor3f(0.0, 0.0, 0.0);
glCallList(wire_object);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
} else if (z == currentLayer) {
glEnable(GL_BLEND);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1.0, 1.0, 1.0, 0.5);
glCallList(point_object);
glDisable(GL_BLEND);
}
glTranslatef( 0, -1, 0 );
}
glTranslatef( 0, voxelData->height(), 0 );
glTranslatef( 1, 0, 0 );
}
glTranslatef( voxelData->width() * -1, 0, 0 );
glTranslatef( 0, 0, -1 );
}
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
void GLVoxelView::resizeGL( int w, int h )
{
glViewport( 0, 0, (GLint)QMIN(w, h), (GLint)QMIN(w, h) );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(-voxelData->width(), voxelData->height(), -voxelData->depth(),
voxelData->width(), -voxelData->height(), voxelData->depth());
glMatrixMode( GL_MODELVIEW );
}
GLuint GLVoxelView::makePointObject()
{
GLuint list;
list = glGenLists( 1 );
glNewList( list, GL_COMPILE );
glBegin(GL_POINTS);
// top
glVertex3f(0, 0, -0.01);
glVertex3f(0, 1, -0.01);
glVertex3f(1, 1, -0.01);
glVertex3f(1, 0, -0.01);
glEnd();
glEndList();
return list;
}
GLuint GLVoxelView::makeWireObject()
{
GLuint list;
list = glGenLists( 1 );
glNewList( list, GL_COMPILE );
glBegin(GL_LINE_STRIP);
// top
glVertex3f(0, 0, -0.01);
glVertex3f(0, 1, -0.01);
glVertex3f(1, 1, -0.01);
glVertex3f(1, 0, 0.01);
glVertex3f(0, 0, 0.01);
glEnd();
glEndList();
return list;
}
GLuint GLVoxelView::makeObject()
{
GLuint list;
list = glGenLists( 1 );
glNewList( list, GL_COMPILE );
glBegin(GL_QUADS);
// front
glNormal3f(0, 1, 0);
glVertex3f(0, 0, 0);
glVertex3f(1, 0, 0);
glVertex3f(1, 0, 1);
glVertex3f(0, 0, 1);
// top
glNormal3f(0, 0, -1);
glVertex3f(0, 0, 0);
glVertex3f(0, 1, 0);
glVertex3f(1, 1, 0);
glVertex3f(1, 0, 0);
// right
glNormal3f(-1, 0, 0);
glVertex3f(1, 0, 0);
glVertex3f(1, 1, 0);
glVertex3f(1, 1, 1);
glVertex3f(1, 0, 1);
// back
glNormal3f(0, -1, 0);
glVertex3f(1, 1, 0);
glVertex3f(0, 1, 0);
glVertex3f(0, 1, 1);
glVertex3f(1, 1, 1);
// left
glNormal3f(1, 0, 0);
glVertex3f(0, 0, 0);
glVertex3f(0, 0, 1);
glVertex3f(0, 1, 1);
glVertex3f(0, 1, 0);
// bottom
glNormal3f(0, 0, -1);
glVertex3f(0, 0, 1);
glVertex3f(1, 0, 1);
glVertex3f(1, 1, 1);
glVertex3f(0, 1, 1);
glEnd();
glEndList();
return list;
}