Nicolas Winkler 5 years ago
parent
commit
c4ee5852d9
4 changed files with 76 additions and 22 deletions
  1. 52 19
      MandelWidget.cpp
  2. 8 3
      MandelWidget.h
  3. 7 0
      libmandel/include/MandelUtil.h
  4. 9 0
      libmandel/src/MandelUtil.cpp

+ 52 - 19
MandelWidget.cpp

@@ -178,15 +178,21 @@ void Calcer::clearAll(void)
 void Calcer::calc(TexGrid& grid, int level, int i, int j)
 {
     if (jobs.find({ level, i, j }) == jobs.end()) {
-        auto job = std::make_unique<Job>(mndContext, gradient, maxIter, &grid, level, i, j);
-        connect(job.get(), &Job::done, this, &Calcer::redirect);
-        jobs.insert({ std::tuple{ level, i, j }, std::move(job) });
-        //jobs.push_back(std::move(job));
-        threadPool->start(job.get());
+        Job* job = new Job(mndContext, gradient, maxIter, &grid, level, i, j);
+        connect(job, &Job::done, this, &Calcer::redirect);
+        connect(job, &QObject::destroyed, this, [this, level, i, j] () { this->notFinished(level, i, j); });
+        jobs.emplace(level, i, j);
+        threadPool->start(job);
     }
 }
 
 
+void Calcer::notFinished(int level, int i, int j)
+{
+    jobs.erase({ level, i, j });
+}
+
+
 void Calcer::redirect(int level, int i, int j, Bitmap<RGBColor>* bmp)
 {
     jobs.erase({ level, i, j });
@@ -234,7 +240,7 @@ TexGrid& MandelV::getGrid(int level)
         return it->second;
     }
     else {
-        levels.insert({ level, TexGrid(getDpp(level)) });
+        levels.insert(std::pair<int, TexGrid>{ level, TexGrid{ getDpp(level) } });
         return levels[level];
     }
 }
@@ -244,13 +250,15 @@ void MandelV::setMaxIter(int maxIter)
 {
     this->maxIter = maxIter;
     calcer.setMaxIter(maxIter);
+    clear();
+    emit redrawRequested();
 }
 
 
 
 void MandelV::clear(void)
 {
-    for(auto[level, grid] : this->levels) {
+    for(auto& [level, grid] : this->levels) {
         grid.clearCells();
     }
 }
@@ -567,8 +575,8 @@ void MandelWidget::paintGL(void)
     v->paint(this->viewport);
     //*tex = std::move(v->empty);
 
-    if (rubberbandDragging)
-        drawRubberband();
+    //if (dragging)
+    //    drawRubberband();
 }
 
 
@@ -584,9 +592,10 @@ void MandelWidget::drawRubberband(void)
 }
 
 
-void MandelWidget::zoom(float scale)
+void MandelWidget::zoom(float scale, float x, float y)
 {
-    viewport.zoomCenter(scale);
+    viewport.zoom(scale, x, y);
+    //viewport.zoomCenter(scale);
     requestRecalc();
 }
 
@@ -651,37 +660,61 @@ void MandelWidget::resizeEvent(QResizeEvent* re)
 
 void MandelWidget::mousePressEvent(QMouseEvent* me)
 {
+    QOpenGLWidget::mousePressEvent(me);
     rubberband.setCoords(me->x(), me->y(), 0, 0);
-    rubberbandDragging = true;
+    dragging = true;
+    dragX = me->x();
+    dragY = me->y();
 }
 
 
 void MandelWidget::mouseMoveEvent(QMouseEvent* me)
 {
-    QRectF& rect = rubberband;
+    QOpenGLWidget::mouseMoveEvent(me);
+    /*QRectF& rect = rubberband;
     float aspect = float(geometry().width()) / geometry().height();
     rect.setBottomRight(QPoint(me->x(), me->y()));
     if (rect.width() > rect.height() * aspect)
         rect.setHeight(rect.width() / aspect);
     else
-        rect.setWidth(rect.height() * aspect);
-    if (rubberbandDragging)
+        rect.setWidth(rect.height() * aspect);*/
+    if (dragging) {
+        float deltaX = me->x() - dragX;
+        float deltaY = me->y() - dragY;
+
+        this->viewport.x -= deltaX * viewport.width / this->width();
+        this->viewport.y -= deltaY * viewport.height / this->height();
+        dragX = me->x(); dragY = me->y();
+
         emit repaint();
+    }
 }
 
 
 void MandelWidget::mouseReleaseEvent(QMouseEvent* me)
 {
-    QRect rect = rubberband.toRect();
+    QOpenGLWidget::mouseReleaseEvent(me);
+    /*QRect rect = rubberband.toRect();
     QRect full = this->geometry();
 
     viewport.x += double(rect.left()) * viewport.width / full.width();
     viewport.y += double(rect.top()) * viewport.height / full.height();
     viewport.width *= double(rect.width()) / full.width();
     viewport.height *= double(rect.height()) / full.height();
-    viewport.normalize();
-    rubberbandDragging = false;
-    requestRecalc();
+    viewport.normalize();*/
+    dragging = false;
+    //requestRecalc();
+}
+
+void MandelWidget::wheelEvent(QWheelEvent* we)
+{
+    QOpenGLWidget::wheelEvent(we);
+    float x = float(we->x()) / this->width();
+    float y = float(we->y()) / this->height();
+    float scale = 1.0f - we->angleDelta().y() * 0.001f;
+    printf("scale: %f\n", double(scale));
+    zoom(scale, x, y);
+    we->accept();
 }
 
 

+ 8 - 3
MandelWidget.h

@@ -82,6 +82,7 @@ public:
 public:
     inline TexGrid(void) : dpp{ 1.0 } {}
     inline TexGrid(double dpp) : dpp{ dpp } {}
+    //TexGrid(const TexGrid&) = delete;
     std::pair<int, int> getCellIndices(double x, double y);
     std::pair<double, double> getPositions(int i, int j);
     Texture* getCell(int i, int j);
@@ -125,7 +126,7 @@ signals:
 class Calcer : public QObject
 {
     Q_OBJECT
-    std::unordered_map<std::tuple<int, int, int>, std::unique_ptr<Job>, TripleHash> jobs;
+    std::unordered_set<std::tuple<int, int, int>, TripleHash> jobs;
     mnd::MandelContext& mndContext;
     std::unique_ptr<QThreadPool> threadPool;
     Gradient& gradient;
@@ -145,6 +146,7 @@ public:
 
 public slots:
     void calc(TexGrid& grid, int level, int i, int j);
+    void notFinished(int level, int i, int j);
     void redirect(int level, int i, int j, Bitmap<RGBColor>* bmp);
 signals:
     void done(int level, int i, int j, Bitmap<RGBColor>* bmp);
@@ -233,8 +235,10 @@ private:
     bool initialized = false;
     int maxIterations = 2000;
 
-    bool rubberbandDragging = false;
+
     QRectF rubberband;
+    bool dragging = false;
+    int dragX, dragY;
 
     std::unique_ptr<Texture> tex;
     mnd::MandelViewport viewport;
@@ -261,7 +265,7 @@ public:
 
     void drawRubberband(void);
 
-    void zoom(float scale);
+    void zoom(float scale, float x = 0.5f, float y = 0.5f);
     void setMaxIterations(int maxIter);
 
     //void redraw();
@@ -272,6 +276,7 @@ public:
     void mousePressEvent(QMouseEvent* me) override;
     void mouseMoveEvent(QMouseEvent* me) override;
     void mouseReleaseEvent(QMouseEvent* me) override;
+    void wheelEvent(QWheelEvent * we) override;
 
     inline const mnd::MandelViewport& getViewport(void) const { return viewport; }
 signals:

+ 7 - 0
libmandel/include/MandelUtil.h

@@ -39,6 +39,13 @@ struct mnd::MandelViewport
     void zoomCenter(float scale);
 
     /*!
+     * \brief zoom in around a specific point
+     * \param x value between 0.0f and 1.0f
+     * \param y value between 0.0f and 1.0f
+     */
+    void zoom(float scale, float x, float y);
+
+    /*!
      * \brief returns a viewport where the whole mandelbrot set can be observed
      */
     static MandelViewport standardView(void);

+ 9 - 0
libmandel/src/MandelUtil.cpp

@@ -33,6 +33,15 @@ void MandelViewport::zoomCenter(float scale)
     height *= scale;
 }
 
+
+void MandelViewport::zoom(float scale, float xz, float yz)
+{
+    this->x += width * (1 - scale) * xz;
+    this->y += height * (1 - scale) * yz;
+    width *= scale;
+    height *= scale;
+}
+
 MandelViewport MandelViewport::standardView(void)
 {
     return MandelViewport{