main
Benjamin Kraft 1 year ago
parent ea344c281c
commit a3d04d3086
  1. 9
      src/MainWindow.cpp
  2. 2
      src/MainWindow.h
  3. 44
      src/Pendulum.cpp

@ -28,7 +28,7 @@ MainWindow::MainWindow() {
} }
void MainWindow::buildUI() { void MainWindow::buildUI() {
setMinimumSize(1000, 400); setMinimumSize(1000, 700);
auto uiLyt = new QVBoxLayout; auto uiLyt = new QVBoxLayout;
glWidget = new GLWidget(simulation); glWidget = new GLWidget(simulation);
@ -287,6 +287,9 @@ QWidget * MainWindow::buildAddUI() {
addBtn->setToolTip("Add configured pendulum"); addBtn->setToolTip("Add configured pendulum");
removeBtn->setToolTip("Remove all pendula"); removeBtn->setToolTip("Remove all pendula");
addBtn->setStyleSheet("background-color: #aaffaa");
removeBtn->setStyleSheet("background-color: #ffaaaa");
connect(addBtn, &QPushButton::clicked, this, &MainWindow::add); connect(addBtn, &QPushButton::clicked, this, &MainWindow::add);
connect(removeBtn, &QPushButton::clicked, this, &MainWindow::remove); connect(removeBtn, &QPushButton::clicked, this, &MainWindow::remove);
@ -341,6 +344,8 @@ QWidget * MainWindow::buildSimulationUI() {
reset->setToolTip("Reset Simulation controls"); reset->setToolTip("Reset Simulation controls");
togglePlay->setToolTip("Pause/Resume Simulation"); togglePlay->setToolTip("Pause/Resume Simulation");
togglePlay->setStyleSheet("background-color: #aaaaff");
connect(reset, &QPushButton::clicked, this, &MainWindow::resetSimulationControl); connect(reset, &QPushButton::clicked, this, &MainWindow::resetSimulationControl);
connect(togglePlay, &QPushButton::clicked, this, &MainWindow::toggleSimulation); connect(togglePlay, &QPushButton::clicked, this, &MainWindow::toggleSimulation);
connect(togglePlay, &QPushButton::clicked, [this, togglePlay](){ connect(togglePlay, &QPushButton::clicked, [this, togglePlay](){
@ -403,7 +408,7 @@ void MainWindow::add() {
break; break;
} }
if (rainbow){ if (rainbow){
auto hue = progress + 0.5; auto hue = float(progress + 0.5);
c = QColor::fromHsvF(hue, 1, 1); c = QColor::fromHsvF(hue, 1, 1);
} }
simulation->pendula.push_back(new Pendulum(M, L, c, angle)); simulation->pendula.push_back(new Pendulum(M, L, c, angle));

@ -17,7 +17,7 @@ private:
QWidget * buildSimulationUI(); QWidget * buildSimulationUI();
Simulation * simulation; Simulation * simulation;
GLWidget * glWidget; GLWidget * glWidget = nullptr;
static const int MaxSegments = 50; static const int MaxSegments = 50;

@ -1,6 +1,7 @@
#include "Pendulum.h" #include "Pendulum.h"
#include <iostream> #include <iostream>
#include <QPainter> #include <QPainter>
#include <QPainterPath>
Pendulum::Pendulum(const std::vector<double> &M, Pendulum::Pendulum(const std::vector<double> &M,
const std::vector<double> &L, const std::vector<double> &L,
@ -20,25 +21,35 @@ Pendulum::Pendulum(const std::vector<double> &M,
void Pendulum::draw(QPainter *p, double scale) const { void Pendulum::draw(QPainter *p, double scale) const {
p->setPen(color); p->setPen(color);
p->setBrush(Qt::white); p->setBrush(Qt::NoBrush);
Vector previousX(0, 0); QPainterPath path;
path.moveTo(0, 0);
for (int i = 0; i < X.size(); i++){ for (auto x : X){
Vector x = X[i] * scale; x = x * scale;
p->drawLine(previousX.x, previousX.y, x.x, x.y); path.lineTo(x.x, x.y);
previousX = x; }
p->drawPath(path);
double r = sqrt(M[i] * scale / 5); p->setBrush(Qt::white);
p->drawEllipse(QPointF(x.x, x.y), r * 2, r * 2); for (int i = 0; i < M.size(); i++){
double r = sqrt(M[i]) * scale / 10;
p->drawEllipse(QPointF(X[i].x, X[i].y) * scale, r * 2, r * 2);
} }
} }
void Pendulum::update(double h, double g) { void Pendulum::update(double h, double g) {
Vector p1(0, 0);
// Classic PBD needs multiple loops
// Here, I can put all operations safely into one single loop,
// because the positions and velocities in X, V are sorted
// from the pendulum's origin to it's end which means
// that only direct neighbours affect each other
Vector p1(0, 0);
for (int i = 0; i < X.size(); i++){ for (int i = 0; i < X.size(); i++){
V[i] = V[i] + Vector(0, g * h);
// explicit integration with gravity as external force
V[i] = V[i] + Vector(0, g * h);
Vector p2 = X[i] + V[i] * h; Vector p2 = X[i] + V[i] * h;
// solve distance constraint // solve distance constraint
@ -56,18 +67,19 @@ void Pendulum::update(double h, double g) {
p1 = p1 + deltaP1; p1 = p1 + deltaP1;
p2 = p2 + deltaP2; p2 = p2 + deltaP2;
// integrate // update position and velocity
if (i > 0){ if (i > 0){
V[i - 1] = (p1 - X[i - 1]) / h; V[i - 1] = (p1 - X[i - 1]) / h;
X[i - 1] = p1; X[i - 1] = p1;
if (i == X.size() - 1){
V[i] = (p2 - X[i]) / h;
X[i] = p2;
}
} }
p1 = p2; p1 = p2;
} }
// integrate last segment
int i = X.size() - 1;
V[i] = (p1 - X[i]) / h;
X[i] = p1;
} }

Loading…
Cancel
Save