261 lines
7.9 KiB
C++
Executable file
261 lines
7.9 KiB
C++
Executable file
#include "opengldisplaywidget.h"
|
|
#include <QMouseEvent>
|
|
#include <QKeyEvent>
|
|
#include <QOpenGLFunctions>
|
|
#include <iostream>
|
|
#include "math.h"
|
|
#include "cartesiangridtohorizontalslicefilter.h"
|
|
#include "horizontalslicetoimagemapper.h"
|
|
#include "horizontalslicerenderer.h"
|
|
#include "flowdatasource.h"
|
|
|
|
#define XValue 16
|
|
#define YValue 16
|
|
#define ZValue 16
|
|
|
|
OpenGLDisplayWidget::OpenGLDisplayWidget(QWidget *parent)
|
|
: QOpenGLWidget(parent),
|
|
distanceToCamera(-8.0)
|
|
{
|
|
setFocusPolicy(Qt::StrongFocus);
|
|
}
|
|
|
|
|
|
OpenGLDisplayWidget::~OpenGLDisplayWidget()
|
|
{
|
|
// Clean up visualization pipeline.
|
|
//delete bboxRenderer;
|
|
delete grid;
|
|
delete filter;
|
|
delete mapper;
|
|
delete renderer;
|
|
delete contourrenderer;
|
|
// ....
|
|
}
|
|
|
|
|
|
QString OpenGLDisplayWidget::openGLString()
|
|
{
|
|
QString profileStr;
|
|
switch (format().profile())
|
|
{
|
|
case QSurfaceFormat::NoProfile:
|
|
profileStr = "no profile";
|
|
break;
|
|
case QSurfaceFormat::CompatibilityProfile:
|
|
profileStr = "compatibility profile";
|
|
break;
|
|
case QSurfaceFormat::CoreProfile:
|
|
profileStr = "core profile";
|
|
break;
|
|
}
|
|
|
|
return QString("%1.%2 (%3)").arg(format().majorVersion())
|
|
.arg(format().minorVersion()).arg(profileStr);
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::initializeGL()
|
|
{
|
|
// Query and display some information about the used OpenGL context.
|
|
std::cout << "Initializing OpenGLDisplayWidget with OpenGL version "
|
|
<< openGLString().toStdString() << ".\n" << std::flush;
|
|
|
|
// Set the backgound color of the OpenGL display enable the depth buffer.
|
|
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
|
f->glClearColor(0, 0, 0, 1);
|
|
f->glEnable(GL_DEPTH_TEST);
|
|
|
|
// Our own initialization of the visualization pipeline.
|
|
initVisualizationPipeline();
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::resizeGL(int w, int h)
|
|
{
|
|
// Calculate aspect ratio of the current viewport.
|
|
float aspectRatio = float(w) / std::max(1, h);
|
|
|
|
// Reset projection and set new perspective projection.
|
|
projectionMatrix.setToIdentity();
|
|
projectionMatrix.perspective(45.0, aspectRatio, 0.05, 25.0);
|
|
|
|
// Update model-view-projection matrix with new projection.
|
|
updateMVPMatrix();
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::paintGL()
|
|
{
|
|
// Clear color and depth buffer.
|
|
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
|
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
// Call renderer modules.
|
|
//bboxRenderer->drawBoundingBox(mvpMatrix);
|
|
renderer->drawBoundingBox(mvpMatrix);
|
|
renderer->drawFrame(mvpMatrix);
|
|
renderer->drawImage(mvpMatrix);
|
|
contourrenderer->draw(mvpMatrix);
|
|
// ....
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::mousePressEvent(QMouseEvent *e)
|
|
{
|
|
// Save the current position of the mouse pointer for subsequent use
|
|
// in mouseMoveEvent().
|
|
lastMousePosition = QVector2D(e->localPos());
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::mouseMoveEvent(QMouseEvent *e)
|
|
{
|
|
// If the user holds the left mouse button while moving the mouse, update
|
|
// the rotation angles that specify from which side the grid visualization
|
|
// is viewed.
|
|
if (e->buttons() & Qt::LeftButton)
|
|
{
|
|
// Vector that points from the last stored position of the mouse
|
|
// pointer to the current position.
|
|
QVector2D mousePosDifference = QVector2D(e->localPos()) - lastMousePosition;
|
|
|
|
// Update rotation angles in x and y direction. The factor "10" is an
|
|
// arbitrary scaling constant that controls the sensitivity of the
|
|
// mouse.
|
|
rotationAngles.setX(
|
|
fmod(rotationAngles.x() + mousePosDifference.x()/10.,
|
|
360.));
|
|
rotationAngles.setY(
|
|
fmod(rotationAngles.y() + mousePosDifference.y()/10.,
|
|
360.));
|
|
|
|
// Store current position of mouse pointer for next call to this method.
|
|
lastMousePosition = QVector2D(e->localPos());
|
|
|
|
// Update model-view-projection matrix with new rotation angles.
|
|
updateMVPMatrix();
|
|
|
|
// Redraw OpenGL.
|
|
update();
|
|
}
|
|
}
|
|
|
|
void OpenGLDisplayWidget::wheelEvent(QWheelEvent *e)
|
|
{
|
|
// Update distance of the camera to the rendered visualization. The factor
|
|
// "500" is arbitrary and controls that sensitivity of the mouse.
|
|
distanceToCamera += e->delta() / 500.;
|
|
|
|
// Update model-view-projection matrix with new distance to camera.
|
|
updateMVPMatrix();
|
|
|
|
// Redraw OpenGL.
|
|
update();
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::keyPressEvent(QKeyEvent *e)
|
|
{
|
|
|
|
if (e->key() == Qt::Key_Up)
|
|
{
|
|
if (renderer->z < ZValue -1) {
|
|
renderer->moveSlice(1);
|
|
filter->setSlice(renderer->z);
|
|
mapper->getSlice(filter->passSlice(XValue,YValue));
|
|
contourmapper->newZ(filter->passSlice(XValue,YValue), renderer->z);
|
|
}
|
|
}
|
|
else if (e->key() == Qt::Key_Down)
|
|
{
|
|
if (renderer->z > 0) {
|
|
renderer->moveSlice(-1);
|
|
filter->setSlice(renderer->z);
|
|
mapper->getSlice(filter->passSlice(XValue,YValue));
|
|
contourmapper->newZ(filter->passSlice(XValue,YValue), renderer->z);
|
|
}
|
|
} else if (e->key() == Qt::Key_X) {
|
|
mapper->setMagnitude(false);
|
|
filter->changeWindComponent(0);
|
|
mapper->getSlice(filter->passSlice(XValue,YValue));
|
|
contourmapper->newZ(filter->passSlice(XValue,YValue), renderer->z);
|
|
} else if (e->key() == Qt::Key_Y) {
|
|
mapper->setMagnitude(false);
|
|
filter->changeWindComponent(1);
|
|
mapper->getSlice(filter->passSlice(XValue,YValue));
|
|
contourmapper->newZ(filter->passSlice(XValue,YValue), renderer->z);
|
|
} else if (e->key() == Qt::Key_Z) {
|
|
mapper->setMagnitude(false);
|
|
filter->changeWindComponent(2);
|
|
mapper->getSlice(filter->passSlice(XValue,YValue));
|
|
contourmapper->newZ(filter->passSlice(XValue,YValue), renderer->z);
|
|
} else if (e->key() == Qt::Key_M) {
|
|
// SPECIAL CASE
|
|
filter->changeWindComponent(0);
|
|
mapper->getSlice(filter->passSlice(XValue,YValue));
|
|
mapper->setMagnitude(true);
|
|
// contour renderer does not work for the magnitude case!
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
// Redraw OpenGL.
|
|
|
|
update();
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::updateMVPMatrix()
|
|
{
|
|
// Calculate a simple model view transformation from rotation angles
|
|
// and distance to camera.
|
|
// NOTE: Read from bottom to top.
|
|
|
|
QMatrix4x4 mvMatrix;
|
|
mvMatrix.translate(0.0, 0.0, distanceToCamera);
|
|
mvMatrix.rotate(rotationAngles.y(), QVector3D(1.0, 0.0, 0.0));
|
|
mvMatrix.rotate(rotationAngles.x(), QVector3D(0.0, 1.0, 0.0));
|
|
mvMatrix.translate(-1.0, -1.0, -1.0);
|
|
mvMatrix.scale(2.0);
|
|
|
|
mvpMatrix = projectionMatrix * mvMatrix;
|
|
}
|
|
|
|
|
|
void OpenGLDisplayWidget::initVisualizationPipeline()
|
|
{
|
|
// Initialize the visualization pipeline:
|
|
|
|
// Initialize data source(s).
|
|
grid = new FlowDataSource();
|
|
grid->createData(XValue,YValue,ZValue, 0);
|
|
|
|
// Initialize filter modules.
|
|
filter = new CartesianGridToHorizontalSliceFilter();
|
|
filter->setDataSource(grid->returnSource());
|
|
filter->setSlice(0);
|
|
filter->setWindComponent(0); // The x-component
|
|
|
|
// Initialize mapper modules.
|
|
mapper = new HorizontalSliceToImageMapper();
|
|
mapper->getSlice(filter->passSlice(XValue,YValue), XValue,YValue);
|
|
|
|
|
|
contourmapper = new HorizontalSliceToContourLineMapper(); //Mapper causes the program to crash
|
|
contourmapper->getSlice(filter->passSlice(XValue,YValue), XValue,YValue,ZValue, 0);
|
|
float *isos = new float[3];
|
|
isos[0] = 0.1;
|
|
isos[1] = 0;
|
|
isos[2] = -0.1;
|
|
contourmapper->setIso(isos, 3);
|
|
delete[] isos;
|
|
|
|
// Initialize rendering modules.
|
|
//bboxRenderer = new DataVolumeBoundingBoxRenderer();
|
|
renderer = new HorizontalSliceRenderer(0, ZValue);
|
|
contourrenderer = new HorizontalContourLinesRenderer();
|
|
renderer->setMapper(mapper);
|
|
contourrenderer->setContourMapper(contourmapper);
|
|
}
|