diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 18dbd3b..b64eb2c 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -28,7 +28,7 @@ MainWindow::MainWindow() { } void MainWindow::buildUI() { - setMinimumSize(1000, 400); + setMinimumSize(1000, 700); auto uiLyt = new QVBoxLayout; glWidget = new GLWidget(simulation); @@ -287,6 +287,9 @@ QWidget * MainWindow::buildAddUI() { addBtn->setToolTip("Add configured pendulum"); removeBtn->setToolTip("Remove all pendula"); + addBtn->setStyleSheet("background-color: #aaffaa"); + removeBtn->setStyleSheet("background-color: #ffaaaa"); + connect(addBtn, &QPushButton::clicked, this, &MainWindow::add); connect(removeBtn, &QPushButton::clicked, this, &MainWindow::remove); @@ -341,6 +344,8 @@ QWidget * MainWindow::buildSimulationUI() { reset->setToolTip("Reset Simulation controls"); togglePlay->setToolTip("Pause/Resume Simulation"); + togglePlay->setStyleSheet("background-color: #aaaaff"); + connect(reset, &QPushButton::clicked, this, &MainWindow::resetSimulationControl); connect(togglePlay, &QPushButton::clicked, this, &MainWindow::toggleSimulation); connect(togglePlay, &QPushButton::clicked, [this, togglePlay](){ @@ -403,7 +408,7 @@ void MainWindow::add() { break; } if (rainbow){ - auto hue = progress + 0.5; + auto hue = float(progress + 0.5); c = QColor::fromHsvF(hue, 1, 1); } simulation->pendula.push_back(new Pendulum(M, L, c, angle)); diff --git a/src/MainWindow.h b/src/MainWindow.h index 16f2eb2..c246cbc 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -17,7 +17,7 @@ private: QWidget * buildSimulationUI(); Simulation * simulation; - GLWidget * glWidget; + GLWidget * glWidget = nullptr; static const int MaxSegments = 50; diff --git a/src/Pendulum.cpp b/src/Pendulum.cpp index f2393a5..b17cf57 100644 --- a/src/Pendulum.cpp +++ b/src/Pendulum.cpp @@ -1,6 +1,7 @@ #include "Pendulum.h" #include #include +#include Pendulum::Pendulum(const std::vector &M, const std::vector &L, @@ -20,25 +21,35 @@ Pendulum::Pendulum(const std::vector &M, void Pendulum::draw(QPainter *p, double scale) const { p->setPen(color); - p->setBrush(Qt::white); - Vector previousX(0, 0); - - for (int i = 0; i < X.size(); i++){ - Vector x = X[i] * scale; - p->drawLine(previousX.x, previousX.y, x.x, x.y); - previousX = x; + p->setBrush(Qt::NoBrush); + QPainterPath path; + path.moveTo(0, 0); + for (auto x : X){ + x = x * scale; + path.lineTo(x.x, x.y); + } + p->drawPath(path); - double r = sqrt(M[i] * scale / 5); - p->drawEllipse(QPointF(x.x, x.y), r * 2, r * 2); + p->setBrush(Qt::white); + 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) { - 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++){ - 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; // solve distance constraint @@ -56,18 +67,19 @@ void Pendulum::update(double h, double g) { p1 = p1 + deltaP1; p2 = p2 + deltaP2; - // integrate + // update position and velocity if (i > 0){ V[i - 1] = (p1 - X[i - 1]) / h; X[i - 1] = p1; + + if (i == X.size() - 1){ + V[i] = (p2 - X[i]) / h; + X[i] = p2; + } } p1 = p2; } - // integrate last segment - int i = X.size() - 1; - V[i] = (p1 - X[i]) / h; - X[i] = p1; }