From dca7cd60bff32f333330915f6355a34a74fccbca Mon Sep 17 00:00:00 2001 From: Jan Burle <jan@c53.be> Date: Thu, 18 May 2017 16:57:37 +0200 Subject: [PATCH] first cut of a lattice demo --- GUI/ba3d/CMakeLists.txt | 3 +- GUI/ba3d/ba3d/model/model.h | 6 +- GUI/ba3d/ba3d/view/canvas.cpp | 4 ++ GUI/ba3d/ba3d/view/canvas.h | 1 + GUI/ba3d/ba3d/widget.cpp | 9 +++ GUI/ba3d/ba3d/widget.h | 3 + GUI/ba3d/demo/CMakeLists.txt | 17 ++++++ GUI/ba3d/demo/demo_model.cpp | 79 ++++++++++++++++++++++++++ GUI/ba3d/demo/demo_model.h | 24 ++++++++ GUI/ba3d/demo/lattice.cpp | 102 ++++++++++++++++++++++++++++++++++ GUI/ba3d/demo/lattice.h | 15 +++++ GUI/ba3d/demo/main.cpp | 45 +++++++++++++++ GUI/ba3d/demo/mainwin.cpp | 61 ++++++++++++++++++++ GUI/ba3d/demo/mainwin.h | 35 ++++++++++++ 14 files changed, 402 insertions(+), 2 deletions(-) create mode 100644 GUI/ba3d/demo/CMakeLists.txt create mode 100644 GUI/ba3d/demo/demo_model.cpp create mode 100644 GUI/ba3d/demo/demo_model.h create mode 100644 GUI/ba3d/demo/lattice.cpp create mode 100644 GUI/ba3d/demo/lattice.h create mode 100644 GUI/ba3d/demo/main.cpp create mode 100644 GUI/ba3d/demo/mainwin.cpp create mode 100644 GUI/ba3d/demo/mainwin.h diff --git a/GUI/ba3d/CMakeLists.txt b/GUI/ba3d/CMakeLists.txt index 92bee32932f..5b53ecb71a4 100644 --- a/GUI/ba3d/CMakeLists.txt +++ b/GUI/ba3d/CMakeLists.txt @@ -18,7 +18,8 @@ include_directories(${include_dirs}) set (CMAKE_AUTOMOC ON) add_subdirectory (ba3d) -add_subdirectory (main) +# add_subdirectory (main) +add_subdirectory (demo) set(library_name ba3d) set(${library_name}_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE) diff --git a/GUI/ba3d/ba3d/model/model.h b/GUI/ba3d/ba3d/model/model.h index b7831eb518b..61cd80e89e6 100644 --- a/GUI/ba3d/ba3d/model/model.h +++ b/GUI/ba3d/ba3d/model/model.h @@ -14,7 +14,8 @@ namespace ba3d { class Canvas; class Object; -class Model { +class Model : public QObject { + Q_OBJECT friend class Canvas; friend class Object; public: @@ -29,6 +30,9 @@ public: xyz defEye, defCtr, defUp; // default camera params +signals: + void updated(); + private: QVector<Object*> objects, objectsBlend; diff --git a/GUI/ba3d/ba3d/view/canvas.cpp b/GUI/ba3d/ba3d/view/canvas.cpp index 793bb65bd8b..7889304a992 100644 --- a/GUI/ba3d/ba3d/view/canvas.cpp +++ b/GUI/ba3d/ba3d/view/canvas.cpp @@ -49,6 +49,10 @@ void Canvas::setModel(Model* m) { setCamera(true); } +Model* Canvas::getModel() { + return model; +} + void Canvas::setCamera(bool full) { if (camera) { camera->setAspectRatio(aspectRatio); diff --git a/GUI/ba3d/ba3d/view/canvas.h b/GUI/ba3d/ba3d/view/canvas.h index 81a00891406..f388cea594c 100644 --- a/GUI/ba3d/ba3d/view/canvas.h +++ b/GUI/ba3d/ba3d/view/canvas.h @@ -30,6 +30,7 @@ public: void setCamera(Camera*); void setProgram(Program*); void setModel(Model*); + Model* getModel(); private: QRect viewport; diff --git a/GUI/ba3d/ba3d/widget.cpp b/GUI/ba3d/ba3d/widget.cpp index 1f3d169daea..4e92772b033 100644 --- a/GUI/ba3d/ba3d/widget.cpp +++ b/GUI/ba3d/ba3d/widget.cpp @@ -31,7 +31,16 @@ void Widget3D::setBackground(QColor const& color) { } void Widget3D::setModel(Model* model) { + disconnect(modelUpdated); canvas->setModel(model); + + connect(model, &Model::updated, [this]() { + update(); + }); +} + +Model* Widget3D::getModel() { + return canvas->getModel(); } void Widget3D::update() { diff --git a/GUI/ba3d/ba3d/widget.h b/GUI/ba3d/ba3d/widget.h index db4147204e7..b71368e051b 100644 --- a/GUI/ba3d/ba3d/widget.h +++ b/GUI/ba3d/ba3d/widget.h @@ -15,6 +15,7 @@ class Camera; class Program; class Widget3D : public QWidget { BASE(QWidget) + Q_OBJECT public: Widget3D(); ~Widget3D(); @@ -23,6 +24,7 @@ public: void setBackground(QColor const&); void setModel(Model*); // model owned elsewhere, may be nullptr + Model* getModel(); void update(); @@ -30,6 +32,7 @@ private: Canvas *canvas; Camera *camera; Program *program; + QMetaObject::Connection modelUpdated; }; //------------------------------------------------------------------------------ diff --git a/GUI/ba3d/demo/CMakeLists.txt b/GUI/ba3d/demo/CMakeLists.txt new file mode 100644 index 00000000000..a19facd3bb8 --- /dev/null +++ b/GUI/ba3d/demo/CMakeLists.txt @@ -0,0 +1,17 @@ +set (app ba3d_app) + +find_package (Qt5Core REQUIRED) +find_package (Qt5Gui REQUIRED) +find_package (Qt5Widgets REQUIRED) +find_package (OpenGL) + +file (GLOB_RECURSE files *) +add_executable (${app} ${files}) + +target_link_libraries (${app} + ba3d + Qt5::Core Qt5::Gui Qt5::Widgets + ${OPENGL_gl_LIBRARY} +) + +# eof diff --git a/GUI/ba3d/demo/demo_model.cpp b/GUI/ba3d/demo/demo_model.cpp new file mode 100644 index 00000000000..a8c2ef42f03 --- /dev/null +++ b/GUI/ba3d/demo/demo_model.cpp @@ -0,0 +1,79 @@ +// GPL3; https://github.com/jburle/ba3d + +#include "demo_model.h" +#include <ba3d/model/layer.h> +#include "lattice.h" +#include <qmath.h> + +//------------------------------------------------------------------------------ + +using namespace ba3d; + +DemoModel::DemoModel() { + flt const sz = 80; //0; + spacing = 20; // of particles + + defEye = xyz(10, 10, sz); + defCtr = xyz(0, 0, -20); + defUp = xyz::_y; + + auto layer = [&](int z1, int z2, QColor color) { + flt s2 = sz /2; + auto l = new Layer(dxyz(dr(-s2,+s2), dr(-s2,+s2), dr(z1, z2))); + color.setAlphaF(.3); + l->color = color; + + addBlend(l); + }; + + layer( 0, -20, Qt::green); + layer(-20, -55, Qt::gray); + + n = qFloor(sz / spacing / 2 - 1); + + calc(0); +} + +void DemoModel::calc(float sigma) { + auto mesh = squareLattice(n, sigma); + for (auto& m: mesh) + m = m * spacing + xyz(0, 0, -20); + + if (ps.empty()) { // first time - init + ps.resize(mesh.count()); + flt R = 6; + for (auto& p: ps) + add((p = new particle::TruncatedSphere(R, R))); + } + + EXPECT (ps.count() == mesh.count()) + + if (activeMesh.empty()) { + activeMesh = mesh; + for (uint i=0; i < ps.count(); ++i) + ps.at(i)->transform(xyz::_0, activeMesh.at(i)); + } else { + float const step = .1; bool go = true; + while (go) { + go = false; + for (uint i=0; i < ps.count(); ++i) { + auto& p = ps.at(i); + auto& newPos = mesh.at(i); + auto& pos = activeMesh[i]; + if (step > (pos - newPos).length()) + pos = newPos; + else { + pos = pos + (newPos - pos).normalized() * step; + go = true; + } + p->transform(xyz::_0, pos); + } +// emit updated(); TODO async + } + } + + emit updated(); +} + +//------------------------------------------------------------------------------ +// eof diff --git a/GUI/ba3d/demo/demo_model.h b/GUI/ba3d/demo/demo_model.h new file mode 100644 index 00000000000..93b6276f16c --- /dev/null +++ b/GUI/ba3d/demo/demo_model.h @@ -0,0 +1,24 @@ +// GPL3; https://github.com/jburle/ba3d + +#ifndef BA3D_DEMOMODEL_LAYERS_H +#define BA3D_DEMOMODEL_LAYERS_H + +#include <ba3d/model/model.h> +#include <ba3d/model/particles.h> + +//------------------------------------------------------------------------------ + +class DemoModel : public ba3d::Model { +public: + DemoModel(); + void calc(float sigma); + +private: + uint n; float spacing; + QVector<ba3d::particle::Particle*> ps; + QVector<ba3d::xyz> activeMesh; +}; + +//------------------------------------------------------------------------------ +#endif +// eof diff --git a/GUI/ba3d/demo/lattice.cpp b/GUI/ba3d/demo/lattice.cpp new file mode 100644 index 00000000000..48db0fcd1d4 --- /dev/null +++ b/GUI/ba3d/demo/lattice.cpp @@ -0,0 +1,102 @@ +// GPL3; https://github.com/jburle/ba3d + +#include "lattice.h" +#include <QtGlobal> +#include <QTime> +#include <qmath.h> + +//------------------------------------------------------------------------------ + +QVector<ba3d::xyz> squareLattice(uint n, float sigma) { + using flt = ba3d::flt; + using xyz = ba3d::xyz; + + auto rand01 = [&]() -> float { + static bool seeded = false; + if (!seeded) { + seeded = true; + qsrand(QTime::currentTime().msec()); + } + return qrand() / float(RAND_MAX); + }; + + auto place00 = [&]() -> xyz { + // https://www.taygeta.com/random/gaussian.html + float x01, y01, w; + + do { + x01 = 2.f * rand01() - 1.f; + y01 = 2.f * rand01() - 1.f; + w = x01 * x01 + y01 * y01; + } while (w >= 1.f); + + w = sqrt(-2.f * qLn(w) / w); + return ba3d::xyz(x01 * w * sigma, y01 * w * sigma, 0); + }; + + auto placeHere = [&](xyz::rc here) -> xyz { + return place00() + here; + }; + + auto placeXY = [&](flt x, flt y) -> xyz { + return placeHere(xyz(x, y, 0)); + }; + + uint nn = (2*n + 1) * (2*n + 1); // total number + + auto mesh = QVector<xyz>(nn); + + auto index = [&](int ix, int iy) -> uint { + int nx = n, ny = n; + EXPECT (-nx <= ix && ix <= +nx) + EXPECT (-ny <= iy && iy <= +ny) + uint i = (2*nx + 1) * (iy + ny) + (ix + nx); + ENSURE (i < nn) + return i; + }; + + auto get = [&](int ix, int iy) -> xyz::rc { + return mesh.at(index(ix, iy)); + }; + + auto isMade = [&](int ix, int iy) -> bool { + return xyz::_0 != mesh.at(index(ix, iy)); + }; + + auto put = [&](int ix, int iy) { + if (!isMade(ix, iy)) + mesh[index(ix, iy)] = placeXY(ix, iy); + }; + + auto growBy1Quadrant = [&](uint n, int mx, int my) { + EXPECT (n > 0) + EXPECT (1 == qAbs(mx) && 1 == qAbs(my)) + + put(0*mx, n*my); put(n*mx, 0*my); + + for (uint i = 1; i < n; ++i) { + put(i*mx, n*my); put(n*mx, i*my); + } + + put(n*mx, n*my); + }; + + auto growBy1 = [&](uint n) { + EXPECT (n > 0) + growBy1Quadrant(n, +1, +1); + growBy1Quadrant(n, +1, -1); + growBy1Quadrant(n, -1, +1); + growBy1Quadrant(n, -1, -1); + }; + + auto growTo = [&](uint n) { + for (uint i = 1; i <= n; ++i) + growBy1(i); + }; + + growTo(n); + return mesh; +}; + +//------------------------------------------------------------------------------ +// eof diff --git a/GUI/ba3d/demo/lattice.h b/GUI/ba3d/demo/lattice.h new file mode 100644 index 00000000000..674b079d281 --- /dev/null +++ b/GUI/ba3d/demo/lattice.h @@ -0,0 +1,15 @@ +// GPL3; https://github.com/jburle/ba3d + +#ifndef BA3D_LATTICE_H +#define BA3D_LATTICE_H + +#include <ba3d/def.h> +#include <QVector> + +//------------------------------------------------------------------------------ + +QVector<ba3d::xyz> squareLattice(uint n, float sigma); // n half-size + +//------------------------------------------------------------------------------ +#endif +// eof diff --git a/GUI/ba3d/demo/main.cpp b/GUI/ba3d/demo/main.cpp new file mode 100644 index 00000000000..a670b5f60a5 --- /dev/null +++ b/GUI/ba3d/demo/main.cpp @@ -0,0 +1,45 @@ +// GPL3; https://github.com/jburle/ba3d + +#include <ba3d/def.h> +#include <ba3d/view/camera.h> + +#include "mainwin.h" +#include "demo_model.h" +#include <QApplication> + +//------------------------------------------------------------------------------ + +class App : public QApplication { BASE(QApplication) +public: + App(int& argc, char* argv[]); + ~App(); + + int exec(); +}; + +App::App(int& argc, char* argv[]) : base(argc, argv) { + setOrganizationName("c53"); + setApplicationName("ba3d"); +} + +App::~App() {} + +int App::exec() { + MainWin win; + win.show(); + + QScopedPointer<DemoModel> model(new DemoModel); + + win.widg3t().setModel(model.data()); + + return base::exec(); +} + +//------------------------------------------------------------------------------ + +int main(int argc, char* argv[]) { + App(argc, argv).exec(); +} + +//------------------------------------------------------------------------------ +// eof diff --git a/GUI/ba3d/demo/mainwin.cpp b/GUI/ba3d/demo/mainwin.cpp new file mode 100644 index 00000000000..5fdff9c8847 --- /dev/null +++ b/GUI/ba3d/demo/mainwin.cpp @@ -0,0 +1,61 @@ +// GPL3; https://github.com/jburle/ba3d + +#include "mainwin.h" +#include "demo_model.h" + +#include <QApplication> +#include <QBoxLayout> +#include <QSlider> +#include <QSettings> +#include <QPushButton> + +//------------------------------------------------------------------------------ + +static QString const MAINWIN_GEOMETRY("MainWin Geometry"); + +MainWin::MainWin() { + setWindowTitle(qApp->applicationName()); + createLayout(); + + QSettings s; + restoreGeometry(s.value(MAINWIN_GEOMETRY).toByteArray()); +} + +void MainWin::closeEvent(QCloseEvent*) { + QSettings s; + s.setValue(MAINWIN_GEOMETRY, saveGeometry()); +} + +void MainWin::createLayout() { + setCentralWidget(new QWidget); + + auto vb = new QVBoxLayout; + centralWidget()->setLayout(vb); + + vb->addWidget((w3d = new ba3d::Widget3D)); + w3d->setBackground(palette().color(QPalette::Background)); + + auto hb = new QHBoxLayout; + vb->addLayout(hb); + + sigmaSlider = new QSlider(Qt::Horizontal); + auto recalcButton = new QPushButton("Recalc"); + + sigmaSlider->setRange(0,30); + sigmaSlider->setSingleStep(5); + sigmaSlider->setTickInterval(5); + sigmaSlider->setTickPosition(QSlider::TicksBelow); + + hb->addStretch(); + hb->addWidget(sigmaSlider); + hb->addWidget(recalcButton); + + connect(recalcButton, &QPushButton::clicked, [this]() { + auto model = dynamic_cast<DemoModel*>(w3d->getModel()); + if (model) + model->calc(sigmaSlider->value() / 100.f); + }); +} + +//------------------------------------------------------------------------------ +// eof diff --git a/GUI/ba3d/demo/mainwin.h b/GUI/ba3d/demo/mainwin.h new file mode 100644 index 00000000000..e82fd25cd61 --- /dev/null +++ b/GUI/ba3d/demo/mainwin.h @@ -0,0 +1,35 @@ +// GPL3; https://github.com/jburle/ba3d + +#ifndef BA3D_MAINWIN_H +#define BA3D_MAINWIN_H + +#include <ba3d/widget.h> +#include <ba3d/model/particles.h> +#include <QMainWindow> + +//------------------------------------------------------------------------------ + +class QSlider; + +class MainWin : public QMainWindow { BASE(QMainWindow) + Q_OBJECT +public: + MainWin(); + + ba3d::Widget3D& widg3t() { + return *w3d; + } + +private: + void closeEvent(QCloseEvent*); + + ba3d::Widget3D *w3d; + QWidget *controls; + QSlider *sigmaSlider; + + void createLayout(); +}; + +//------------------------------------------------------------------------------ +#endif +// eof -- GitLab