This commit is contained in:
Turingon 2024-06-15 20:50:23 +02:00
parent b9a6c6c41f
commit 11cc562018
27 changed files with 139 additions and 67 deletions

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 9.0.2, 2024-06-06T23:39:16. -->
<!-- Written by QtCreator 9.0.2, 2024-06-15T12:08:23. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View file

@ -25,9 +25,20 @@ void FlowDataSource::createData(int x, int y, int z, int t) {
num_x = x;
num_y = y;
num_z = z;
ct = t;
delete[] cartesianDataGrid; // Prevents data leaks
cartesianDataGrid = new float[3*x*y*z];
gen_tornado(num_x, num_y, num_z, t, cartesianDataGrid);
gen_tornado(num_x, num_y, num_z, ct, cartesianDataGrid);
}
void FlowDataSource::updateT() {
ct++;
gen_tornado(num_x, num_y, num_z, ct, cartesianDataGrid);
}
void FlowDataSource::resetT() {
ct=0;
gen_tornado(num_x, num_y, num_z, ct, cartesianDataGrid);
}
float FlowDataSource::getDataValue(int iz, int iy, int ix, int ic) {

View file

@ -14,11 +14,14 @@ public:
void printSpeedValuesOfHorizontalSlice(int iz);
void printLargestSpeed(int iz);
float *returnSource();
void updateT();
void resetT();
private:
float *cartesianDataGrid;
int num_x;
int num_y;
int num_z;
int ct;
};
#endif // FLOWDATASOURCE_H

View file

@ -56,15 +56,6 @@ void HorizontalContourLinesRenderer::initContours()
{
vertexBuffer.create(); // Make sure to destroy it in the destructor!
QOpenGLVertexArrayObject::Binder vaoBinder(&vertexArrayObject);
if (vertexArrayObject.isCreated())
{
vertexBuffer.bind();
shaderProgram.setAttributeBuffer("vertexPosition", GL_FLOAT, 0, 3, sizeof(QVector3D));
shaderProgram.enableAttributeArray("vertexPosition");
vertexBuffer.release();
}
}
@ -73,7 +64,7 @@ void HorizontalContourLinesRenderer::draw(QMatrix4x4 mvpMatrix)
QVector<QVector3D> vectors = mapper->mapSliceToContourLineSegments(); //THIS CAUSES THE CRASH
vertexBuffer.bind();
vertexBuffer.allocate(vectors.constData(), vectors.size() * sizeof(QVector3D)); //the .constData() is from a forum post, very strange, idk what it does... hmm but where can we use data()?
vertexBuffer.allocate(vectors.data(), vectors.size() * sizeof(QVector3D)); //the .constData() is from a forum post, very strange, idk what it does... hmm but where can we use data()?
vertexBuffer.release();
QOpenGLVertexArrayObject::Binder vaoBinder(&vertexArrayObject);
@ -97,7 +88,7 @@ void HorizontalContourLinesRenderer::draw(QMatrix4x4 mvpMatrix)
// Issue OpenGL draw commands.
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glLineWidth(3);
f->glLineWidth(4);
f->glDrawArrays(GL_LINES, 0, vectors.size()); // GL_LINES verbindet Vektore paarenweise, wahrend GL_LINE_STRIP jeden Vektor mit seinen 2 Nachbarn im Array verbindet
// Release objects until next render cycle.

View file

@ -11,6 +11,18 @@ HorizontalSliceRenderer::HorizontalSliceRenderer()
initOpenGLShaders();
initBoundingBoxGeometry();
initFrame();
}
HorizontalSliceRenderer::HorizontalSliceRenderer(int zy, int zsy)
: vertexBuffer(QOpenGLBuffer::VertexBuffer)
{
z=zy;
zs=zsy;
initOpenGLShaders();
initBoundingBoxGeometry();
initFrame();
}
HorizontalSliceRenderer::~HorizontalSliceRenderer()
@ -110,7 +122,7 @@ void HorizontalSliceRenderer::initBoundingBoxGeometry()
void HorizontalSliceRenderer::moveSlice(int steps) {
z += steps;
float zeddy = float(z)/15.0;
float zeddy = float(z)/float(zs-1);
const unsigned int numVertices = 5;
float unitFrameVertices[numVertices][3] = {
{0, 0, zeddy}, {1, 0, zeddy}, {1, 1, zeddy}, {0, 1, zeddy}, {0, 0, zeddy}};
@ -126,8 +138,8 @@ void HorizontalSliceRenderer::moveSlice(int steps) {
void HorizontalSliceRenderer::initFrame() {
// Works analogously to the init of the Bounding Box
const unsigned int numVertices = 5;
z = 3;
float zeddy = float(z)/15.0;
float zeddy = float(z)/float(zs-1);
std::cout << zeddy << std::endl;
float unitFrameVertices[numVertices][3] = {
{0, 0, zeddy}, {1, 0, zeddy}, {1, 1, zeddy}, {0, 1, zeddy}, {0, 0, zeddy}};

View file

@ -20,9 +20,11 @@ public:
int z;
void moveSlice(int steps);
void drawCube(QMatrix4x4 mvpMatrix);
HorizontalSliceRenderer(int z, int zs);
private:
void initOpenGLShaders();
void initBoundingBoxGeometry();
int zs;
HorizontalSliceToImageMapper* mapper;
QOpenGLShaderProgram shaderProgram;

View file

@ -11,14 +11,23 @@ HorizontalSliceToContourLineMapper::~HorizontalSliceToContourLineMapper() {
//delete[] isolist;
}
void HorizontalSliceToContourLineMapper::getSlice(float *source, int x, int y, int z) {
void HorizontalSliceToContourLineMapper::getSlice(float *source, int x, int y, int z, int current_z) {
// Sets up the variables
slice = source;
xs = x;
ys = y;
zs = z;
iz = current_z;
}
void HorizontalSliceToContourLineMapper::newZ(float* newsource, int z) {
// updates the mapper pointer and sets a new z-slice
slice = newsource;
iz = z;
}
void HorizontalSliceToContourLineMapper::setIso(float* isos, int nums) {
isolist = new float[nums];
for (int i=0; i<nums; i++) {
isolist[i] = isos[i];
@ -26,8 +35,9 @@ void HorizontalSliceToContourLineMapper::setIso(float* isos, int nums) {
numIsos = nums;
}
char HorizontalSliceToContourLineMapper::marchingSquaresNum(float isoline, float v0, float v1,float v2,float v3) {
// Char used to reduce memory usage, since number small
int HorizontalSliceToContourLineMapper::marchingSquaresNum(float isoline, float v0, float v1,float v2,float v3) {
// The idea is to check which vertices lie above the isoline-value. Each vertex is equal to 2^n
// We do this because we can describe each of the 15 cases uniquely using a 4-bit binary number
char result = 0;
if (isoline<v0) {
result +=1;
@ -42,25 +52,29 @@ char HorizontalSliceToContourLineMapper::marchingSquaresNum(float isoline, float
}
QVector<QVector3D> HorizontalSliceToContourLineMapper::mapSliceToContourLineSegments() {
QVector<QVector3D> vectors;
QVector3D vector1;
QVector<QVector3D> vectors; // We store all of our points in a dynamic array as Vector3Ds
QVector3D vector1; // Vector 1 and 2 will then be connected as a line (using GL_LINES)
QVector3D vector2;
char squareCase = 0;
float v0, v1, v2, v3, iso;
float z_value = float(iz)/(xs-1);
int squareCase = 0; // Initially I used char here, but I swapped it with int, because debugging was hell
float v0, v1, v2, v3, iso; // Initializing values we'll soon be needing
float z_value = float(iz)/(zs-1);
float x_value, y_value;
for (int i = 0; i < numIsos; i++) {
std::cout << "iso: " << isolist[i]; //float
// We loop through all the isolines
//std::cout << "iso: " << isolist[i]; //we check what is in the isolist; a leftover from the debug times
for (int y=0; y< ys-1; y++) {
// Here we loop through all x and y values except for the last one, because we actually loop
// through squares with vertices x, x+1, y and y+1.
for (int x=0; x< xs-1; x++) {
// Watch out! The notation has been taken from the lecture
v3 = slice[3*((y+1)*xs+x)]; //top left
v2 = slice[3*((y+1)*xs+x+1)]; //top right
v1 = slice[3*(y*xs+x)]; //botom left
v0 = slice[3*(y*xs+x+1)]; //bottom right
v1 = slice[3*(y*xs+x+1)]; //botom right
v0 = slice[3*(y*xs+x)]; //bottom left
iso = isolist[i];
squareCase = marchingSquaresNum(iso, v0, v1, v2, v3);
// Viet found the amazing way of reducing the number of cases
// Viet found the amazing way of reducing the number of cases (before that I used switch x3)
// We use if-instructions because Switch doesn't allow for the or operation
// Lookuptable is nonetheless very mechanical
if (squareCase==1 || squareCase==14) {
@ -77,59 +91,82 @@ QVector<QVector3D> HorizontalSliceToContourLineMapper::mapSliceToContourLineSegm
} else if (squareCase==2 || squareCase==13) {
x_value = float(x)/(xs-1);
x_value = float(x+1)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1));
vector1 = QVector3D(x_value,y_value,z_value);
x_value = float(x)/(xs-1)+(iso-v1)/((xs-1)*(v0-v1));
x_value = float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0));
y_value = float(y)/(ys-1);
vector2 = QVector3D(x_value, y_value,z_value);
} else if (squareCase==3 || squareCase==12) {
x_value = float(x)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1));
y_value = float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0));
vector1 = QVector3D(x_value,y_value,z_value);
x_value = float(x)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0));
x_value = float(x+1)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1));
vector2 = QVector3D(x_value,y_value,z_value);
} else if (squareCase==4 || squareCase==11) {
x_value = float(x)/(xs-1);
x_value = float(x+1)/(xs-1);
y_value = float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1));
vector1 = QVector3D(x_value, y_value, z_value);
x_value = float(x)/(xs-1)+(iso-v2)/((xs-1)*(v3-v2));
y_value = float(y)/(ys-1);
x_value = float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3));
y_value = float(y+1)/(ys-1);
vector2 = QVector3D(x_value,y_value,z_value);
} else if (squareCase==5 || squareCase==10) {
} else if (squareCase==5) {
//Special case requires checking is the centre is positive
if (0.25*(v0+v1+v2+v3)>v2) {
vector1 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v2)/((xs-1)*(v3-v2)),float(y)/(ys-1),z_value);
std::cout << 0.25*(v0+v1+v2+v3) << std::endl;
if (0.25*(v0+v1+v2+v3)>iso) {
std::cout << "Gi funkcias!" << std::endl;
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
} else {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v2)/((xs-1)*(v3-v2)),float(y)/(ys-1),z_value);
vector1 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v2)/((ys-1)*(v3-v2)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v1)/((xs-1)*(v2-v1)),float(y)/(ys-1),z_value);
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v3)/((ys-1)*(v2-v3)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
}
} else if (squareCase==10) {
//Special case requires checking is the centre is positive
std::cout << 0.25*(v0+v1+v2+v3) << std::endl;
if (0.25*(v0+v1+v2+v3)>iso) {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v3)/((ys-1)*(v2-v3)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
} else {
std::cout << "Gi funkcias!" << std::endl;
vector1 = QVector3D(float(x+1)/(xs-1),float(y)/(ys-1)+(iso-v1)/((ys-1)*(v2-v1)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vectors << vector1 << vector2;
vector1 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
}
} else if (squareCase==6 || squareCase==9) {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v0)/((xs-1)*(v1-v0)),float(y)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v2)/((xs-1)*(v3-v2)),float(y)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
} else if (squareCase==7 || squareCase==8) {
vector1 = QVector3D(float(x)/(xs-1)+(iso-v2)/((xs-1)*(v3-v2)),float(y)/(ys-1),z_value);
vector1 = QVector3D(float(x)/(xs-1)+(iso-v3)/((xs-1)*(v2-v3)),float(y+1)/(ys-1),z_value);
vector2 = QVector3D(float(x)/(xs-1),float(y)/(ys-1)+(iso-v0)/((ys-1)*(v3-v0)),z_value);
} else {
// cases 0 and 15 are the ones where we draw no lines and they belong here
continue;
}
vectors << vector1 << vector2;

View file

@ -9,13 +9,15 @@ class HorizontalSliceToContourLineMapper
public:
HorizontalSliceToContourLineMapper();
~HorizontalSliceToContourLineMapper();
void getSlice(float *source, int x, int y, int z);
void getSlice(float *source, int x, int y, int z, int current_z);
QVector<QVector3D> mapSliceToContourLineSegments();
char marchingSquaresNum(float isoline, float a, float b, float c, float d);
int marchingSquaresNum(float isoline, float a, float b, float c, float d);
void setIso(float *isos, int nums);
void newZ(float *newsource, int z);
private:
int xs;
int ys;
int zs;
int iz;
int numIsos;
float *slice;

View file

@ -3,6 +3,13 @@ uniform mat4 mvpMatrix; // model-view-projection matrix
in vec4 vertexPosition;
void main()
{
gl_Position = mvpMatrix * vertexPosition; // same kiel antaux
// My image was 90' rotated in the clockwise direction and I don't
// know exactly why, but my Ansatz was to simply rotate the rendered
// image by 90'
float radians = -90.0 * 3.1416 / 180.0;
vec4 newImage;
newImage = vec4(cos(radians) * vertexPosition.x - sin(radians) * vertexPosition.y,1+ sin(radians) * vertexPosition.x + cos(radians) * vertexPosition.y, vertexPosition.z, vertexPosition.w);
gl_Position = mvpMatrix * newImage; // same kiel antaux
}

View file

@ -8,7 +8,6 @@ void main()
// Calculate vertex position in screen space.
gl_Position = mvpMatrix * vertexPosition;
// Originally texCoord = vertexPosition.xy, but this yields a flipped image
//texCoord = vec2(vertexPosition.x, 1.0 - vertexPosition.y);
texCoord = vertexPosition.xy;
texCoord = vec2(vertexPosition.x, 1.0-vertexPosition.y); // Was really only useful for our UHH image
}

41
datenvisualisierung_sose2024/opengldisplaywidget.cpp Normal file → Executable file
View file

@ -9,6 +9,9 @@
#include "horizontalslicerenderer.h"
#include "flowdatasource.h"
#define XValue 16
#define YValue 16
#define ZValue 16
OpenGLDisplayWidget::OpenGLDisplayWidget(QWidget *parent)
: QOpenGLWidget(parent),
@ -157,10 +160,11 @@ void OpenGLDisplayWidget::keyPressEvent(QKeyEvent *e)
if (e->key() == Qt::Key_Up)
{
if (renderer->z < 15) {
if (renderer->z < ZValue -1) {
renderer->moveSlice(1);
filter->setSlice(renderer->z);
mapper->getSlice(filter->passSlice(16,16));
mapper->getSlice(filter->passSlice(XValue,YValue));
contourmapper->newZ(filter->passSlice(XValue,YValue), renderer->z);
}
}
else if (e->key() == Qt::Key_Down)
@ -168,25 +172,30 @@ void OpenGLDisplayWidget::keyPressEvent(QKeyEvent *e)
if (renderer->z > 0) {
renderer->moveSlice(-1);
filter->setSlice(renderer->z);
mapper->getSlice(filter->passSlice(16,16));
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(16,16));
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(16,16));
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(16,16));
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(16,16));
mapper->getSlice(filter->passSlice(XValue,YValue));
mapper->setMagnitude(true);
// contour renderer does not work for the magnitude case!
}
else
{
@ -221,31 +230,31 @@ void OpenGLDisplayWidget::initVisualizationPipeline()
// Initialize data source(s).
grid = new FlowDataSource();
grid->createData(16,16,16, 1);
grid->createData(XValue,YValue,ZValue, 0);
// Initialize filter modules.
filter = new CartesianGridToHorizontalSliceFilter();
filter->setDataSource(grid->returnSource());
filter->setSlice(3);
filter->setSlice(0);
filter->setWindComponent(0); // The x-component
// Initialize mapper modules.
mapper = new HorizontalSliceToImageMapper();
mapper->getSlice(filter->passSlice(16,16), 16, 16);
mapper->getSlice(filter->passSlice(XValue,YValue), XValue,YValue);
contourmapper = new HorizontalSliceToContourLineMapper(); //Mapper causes the program to crash
contourmapper->getSlice(filter->passSlice(16,16), 16, 16, 3);
float *isos = new float[1];
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, 1);
isos[1] = 0;
isos[2] = -0.1;
contourmapper->setIso(isos, 3);
delete[] isos;
// Initialize rendering modules.
//bboxRenderer = new DataVolumeBoundingBoxRenderer();
renderer = new HorizontalSliceRenderer();
renderer = new HorizontalSliceRenderer(0, ZValue);
contourrenderer = new HorizontalContourLinesRenderer();
renderer->setMapper(mapper);
contourrenderer->setContourMapper(contourmapper);

View file

@ -2,7 +2,6 @@
#define OPENGLDISPLAYWIDGET_H
#include <QOpenGLWidget>
#include "datavolumeboundingboxrenderer.h"
#include "flowdatasource.h"
#include "cartesiangridtohorizontalslicefilter.h"
#include "horizontalslicetoimagemapper.h"