add basics, new signal for changed pendulums, added shaders

main
Benjamin Kraft 1 year ago
parent 2acb74bb44
commit 81f5f3fe7b
  1. 2
      CMakeLists.txt
  2. 9
      shaders/fragment.glsl
  3. 6
      shaders/shaders.qrc
  4. 11
      shaders/vertex.glsl
  5. 86
      src/GLWidget.cpp
  6. 17
      src/GLWidget.h
  7. 3
      src/MainWindow.cpp
  8. 3
      src/Pendulum.h
  9. 13
      src/Simulation.cpp
  10. 5
      src/Simulation.h

@ -10,6 +10,6 @@ find_package(Qt6 COMPONENTS OpenGLWidgets REQUIRED)
find_package(OpenMP REQUIRED) find_package(OpenMP REQUIRED)
file(GLOB_RECURSE SOURCE_FILES src/**.cpp) file(GLOB_RECURSE SOURCE_FILES src/**.cpp)
add_executable(Pendulum WIN32 ${SOURCE_FILES} icons/icons.qrc) add_executable(Pendulum WIN32 ${SOURCE_FILES} icons/icons.qrc shaders/shaders.qrc)
target_link_libraries(Pendulum Qt6::OpenGLWidgets OpenMP::OpenMP_CXX) target_link_libraries(Pendulum Qt6::OpenGLWidgets OpenMP::OpenMP_CXX)

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
in vec3 color;
void main() {
FragColor = vec4(color, 1);
}

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/shaders/">
<file>vertex.glsl</file>
<file>fragment.glsl</file>
</qresource>
</RCC>

@ -0,0 +1,11 @@
#version 330 core
layout (location = 0) in vec2 vPos;
layout (location = 1) in vec3 vColor;
out vec3 color;
void main() {
gl_Position = vec4(vPos, 0.0, 1.0);
color = vColor;
}

@ -7,29 +7,93 @@
#include <QApplication> #include <QApplication>
#include <QDialog> #include <QDialog>
#include "FPS.h" #include "FPS.h"
#include <QOpenGLShaderProgram>
GLWidget::GLWidget(Simulation * simulation) : simulation(simulation) { GLWidget::GLWidget(Simulation * simulation) : simulation(simulation) {
startTimer(1000 / 144); startTimer(1000 / 144);
fps = new FPS; fps = new FPS;
fps->setUpdateInterval(500); fps->setUpdateInterval(500);
connect(simulation, &Simulation::pendulaChanged, this, &GLWidget::initGPUMemory);
} }
void GLWidget::paintEvent(QPaintEvent *e) { void GLWidget::initializeGL() {
fps->newFrame(); initializeOpenGLFunctions();
QString fpsString = "FPS: " + QString::fromStdString(std::to_string(fps->current)); glEnable(GL_PRIMITIVE_RESTART);
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
glClearColor(.15, .15, .15, 1);
program = new QOpenGLShaderProgram;
program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vertex.glsl");
program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fragment.glsl");
program->link();
program->bind();
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
float vertices[] = {
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
-0.5, 0.5
};
float colors[] = {
1, 0, 0,
0, 1, 0,
0, 0, 1,
1, 1, 0
};
GLushort indices[] = {
0, 1, 0xffff, 2, 3
};
glGenBuffers(1, &positionVBO);
glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
GLuint colorVBO;
glGenBuffers(1, &colorVBO);
glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glEnableVertexAttribArray(1);
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindVertexArray(0);
}
void GLWidget::paintGL() {
auto p = new QPainter(this); auto p = new QPainter(this);
p->setRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::Antialiasing);
p->fillRect(e->rect(), QColor(30, 30, 30)); p->beginNativePainting();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, QWidget::width(), QWidget::height());
program->bind();
glBindVertexArray(VAO);
glDrawElements(GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, nullptr);
simulation->draw(nullptr, std::min(width(), height()));
glBindVertexArray(0);
p->endNativePainting();
p->setPen(Qt::white); p->setPen(Qt::white);
auto font = p->font(); auto font = p->font();
font.setPixelSize(20); font.setPixelSize(20);
p->setFont(font); p->setFont(font);
p->drawText(0, 0, 400, 400, Qt::AlignTop | Qt::AlignLeft, fpsString);
p->translate(e->rect().center());
simulation->draw(p, std::min(width(), height())); fps->newFrame();
QString fpsString = "FPS: " + QString::fromStdString(std::to_string(fps->current));
p->drawText(0, 0, 100, 100, Qt::AlignTop | Qt::AlignLeft, fpsString);
p->end(); p->end();
} }
@ -46,4 +110,12 @@ bool GLWidget::AnyDialogOpen() {
return false; return false;
} }
void GLWidget::initGPUMemory(const std::vector<Pendulum *> &addPendula) {
glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
auto positions = (GLfloat*) glMapBufferRange(GL_ARRAY_BUFFER, 0, 2 * 3 * sizeof(float), GL_MAP_WRITE_BIT);
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

@ -1,18 +1,25 @@
#include <QOpenGLWidget> #include <QOpenGLWidget>
#include <QOpenGLFunctions> #include <QOpenGLExtraFunctions>
class Pendulum;
class Simulation; class Simulation;
class FPS; class FPS;
class QOpenGLShaderProgram;
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions { class GLWidget : public QOpenGLWidget, protected QOpenGLExtraFunctions {
public: public:
explicit GLWidget(Simulation *); explicit GLWidget(Simulation *);
protected: protected:
void paintEvent(QPaintEvent* e) override;
void timerEvent(QTimerEvent* e) override; void timerEvent(QTimerEvent* e) override;
void initializeGL() override;
void paintGL() override;
private slots:
void initGPUMemory(const std::vector<Pendulum *> &addPendula);
private: private:
QOpenGLShaderProgram * program;
GLuint VAO;
GLuint positionVBO;
GLsizei indexCount;
Simulation * simulation; Simulation * simulation;
FPS * fps; FPS * fps;
static bool AnyDialogOpen(); static bool AnyDialogOpen();

@ -30,6 +30,9 @@ MainWindow::MainWindow() {
resetLengths(); resetLengths();
buildUI(); buildUI();
normalizeLengths();
add();
} }
void MainWindow::buildUI() { void MainWindow::buildUI() {

@ -1,3 +1,5 @@
#pragma once
#include <vector> #include <vector>
#include <QVector2D> #include <QVector2D>
#include <QColor> #include <QColor>
@ -13,7 +15,6 @@ public:
void draw(QPainter*, double) const; void draw(QPainter*, double) const;
void update(double, double); void update(double, double);
private: private:
std::vector<Vector> X, V; std::vector<Vector> X, V;
std::vector<double> M, L; std::vector<double> M, L;

@ -1,5 +1,4 @@
#include "Simulation.h" #include "Simulation.h"
#include "Pendulum.h"
#include <QPainter> #include <QPainter>
#include <QTimer> #include <QTimer>
#include <QThread> #include <QThread>
@ -19,8 +18,12 @@ void Simulation::draw(QPainter *p, int screenSize) {
double scale = screenSize * 0.95 / size; double scale = screenSize * 0.95 / size;
/*
for (const auto pendulum : pendula) for (const auto pendulum : pendula)
pendulum->draw(p, scale); pendulum->draw(p, scale);
*/
pendulaMutex.unlock(); pendulaMutex.unlock();
} }
@ -52,10 +55,18 @@ void Simulation::clearPendula() {
pendula.shrink_to_fit(); pendula.shrink_to_fit();
pendulaMutex.unlock(); pendulaMutex.unlock();
emit pendulaChanged(pendula);
} }
void Simulation::addPendula(const std::vector<Pendulum *> &add) { void Simulation::addPendula(const std::vector<Pendulum *> &add) {
pendulaMutex.lock();
for (auto p : add) for (auto p : add)
pendula.push_back(p); pendula.push_back(p);
pendulaMutex.unlock();
emit pendulaChanged(pendula);
} }

@ -3,14 +3,15 @@
#include <QObject> #include <QObject>
#include <chrono> #include <chrono>
#include <mutex> #include <mutex>
#include "Pendulum.h"
using namespace std::chrono; using namespace std::chrono;
class Pendulum;
class QPainter; class QPainter;
class QTimer; class QTimer;
class Simulation : public QObject { class Simulation : public QObject {
Q_OBJECT
public: public:
explicit Simulation(); explicit Simulation();
@ -23,6 +24,8 @@ public:
bool isPlaying = false; bool isPlaying = false;
void draw(QPainter*, int); void draw(QPainter*, int);
signals:
void pendulaChanged(const std::vector<Pendulum *> &newPendula);
public slots: public slots:
void clearPendula(); void clearPendula();
void addPendula(const std::vector<Pendulum *> &add); void addPendula(const std::vector<Pendulum *> &add);

Loading…
Cancel
Save