Tornado-Visualization/datenvisualisierung_sose2024/opengldisplaywidget.cpp
2024-07-05 21:38:40 +02:00

308 lines
9.7 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 grid size here
#define XValue 16
#define YValue 16
#define ZValue 16
OpenGLDisplayWidget::OpenGLDisplayWidget(QWidget *parent)
: QOpenGLWidget(parent),
distanceToCamera(-8.0)
{
setFocusPolicy(Qt::StrongFocus);
animate = false;
timey = new QTimer(this);
connect(timey, &QTimer::timeout, this, QOverload<>::of(&OpenGLDisplayWidget::animateVisual));
}
OpenGLDisplayWidget::~OpenGLDisplayWidget()
{
// Cleans up visualization pipeline
//delete bboxRenderer;
delete grid;
delete filter;
delete mapper;
delete renderer;
delete contourrenderer;
delete streamlinemapper;
delete streamlinerenderer;
// ....
}
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);
// Calls renderer modules
//bboxRenderer->drawBoundingBox(mvpMatrix);
renderer->drawBoundingBox(mvpMatrix);
renderer->drawFrame(mvpMatrix);
renderer->drawImage(mvpMatrix);
contourrenderer->draw(mvpMatrix);
streamlinerenderer->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)
{
// This function looks for key presses and then executes the corresponding command
// up and down move the slice up and down
// x,y,z and m activate various wind components or display the magnitude
// note that we only need to change the i in the Filter pointer, which is why
// this implementation should be fast
// Space starts an animation (implemented with a timer)
// R resets the time
// left and right enable the user to check specific times
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);
contourmapper->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);
contourmapper->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);
contourmapper->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);
contourmapper->setMagnitude(true);
} else if (e->key() == Qt::Key_Right) {
std::cout << "Right press\n";
grid->updateT();
} else if (e->key() == Qt::Key_Left) {
grid->decreaseT();
} else if (e->key() == Qt::Key_Space) {
if (!animate) {
animate = !animate;
timey->start(34); // 30Hz/FPS
std::cout << "Animation started\n";
} else {
timey->stop();
animate = !animate;
std::cout << "Animation closed\n";
}
} else if (e->key() == Qt::Key_R){
grid->resetT();
} 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::animateVisual() {
grid->updateT();
update();
}
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 caused the program to crash, but not anymore
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;
streamlinemapper = new StreamlineMapper();
streamlinemapper->getData(filter->passCube(), XValue, YValue, ZValue);
streamlinemapper->setValues(1000, 100);
//streamlinemapper->setValues(125, 100);
// Initialize rendering modules.
//bboxRenderer = new DataVolumeBoundingBoxRenderer();
renderer = new HorizontalSliceRenderer(0, ZValue);
contourrenderer = new HorizontalContourLinesRenderer();
renderer->setMapper(mapper);
contourrenderer->setContourMapper(contourmapper);
streamlinerenderer = new StreamlineRenderer();
streamlinerenderer->setMapper(streamlinemapper);
}