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() {
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));

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

@ -1,6 +1,7 @@
#include "Pendulum.h"
#include <iostream>
#include <QPainter>
#include <QPainterPath>
Pendulum::Pendulum(const std::vector<double> &M,
const std::vector<double> &L,
@ -20,25 +21,35 @@ Pendulum::Pendulum(const std::vector<double> &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;
}

Loading…
Cancel
Save