|
@@ -11,7 +11,7 @@ Texture::Texture(const Bitmap<RGBColor>& bitmap, GLint param)
|
|
|
glGenTextures(1, &id);
|
|
|
glBindTexture(GL_TEXTURE_2D, id);
|
|
|
|
|
|
- long lineLength = (bitmap.width * 3 + 3) & ~3;
|
|
|
+ int lineLength = (bitmap.width * 3 + 3) & ~3;
|
|
|
|
|
|
unsigned char* pixels = new unsigned char[lineLength * bitmap.height];
|
|
|
for (int i = 0; i < bitmap.width; i++) {
|
|
@@ -109,24 +109,23 @@ void TextureClip::drawRect(float x, float y, float width, float height)
|
|
|
|
|
|
TextureClip TextureClip::clip(float x, float y, float w, float h)
|
|
|
{
|
|
|
- TextureClip result(this->texture);
|
|
|
- result.tx = this->tx + x * this->tw;
|
|
|
- result.ty = this->ty + y * this->th;
|
|
|
- result.tw = this->tw * w;
|
|
|
- result.th = this->th * h;
|
|
|
- return result;
|
|
|
+ float tx = this->tx + x * this->tw;
|
|
|
+ float ty = this->ty + y * this->th;
|
|
|
+ float tw = this->tw * w;
|
|
|
+ float th = this->th * h;
|
|
|
+ return TextureClip{ this->texture, tx, ty, tw, th };
|
|
|
}
|
|
|
|
|
|
|
|
|
std::shared_ptr<CellImage> TextureClip::clip(short i, short j)
|
|
|
{
|
|
|
- return std::make_shared<TextureClip>(clip(i * 0.5, j * 0.5, 0.5, 0.5));
|
|
|
+ return std::make_shared<TextureClip>(clip(i * 0.5f, j * 0.5f, 0.5f, 0.5f));
|
|
|
}
|
|
|
|
|
|
|
|
|
int TextureClip::getRecalcPriority() const
|
|
|
{
|
|
|
- return int(1.0 / tw);
|
|
|
+ return int(1.0f / tw);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -139,7 +138,10 @@ void QuadImage::drawRect(float x, float y, float width, float height)
|
|
|
{
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
for (int j = 0; j < 2; j++) {
|
|
|
- this->cells[i][j]->drawRect(x + i * 0.5 * width, y + j * 0.5 * height, width * 0.5, height * 0.5);
|
|
|
+ this->cells[i][j]->drawRect(x + i * 0.5f * width,
|
|
|
+ y + j * 0.5f * height,
|
|
|
+ width * 0.5f,
|
|
|
+ height * 0.5f);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -156,7 +158,7 @@ int QuadImage::getRecalcPriority() const
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-TexGrid::TexGrid(MandelV& owner, int level) :
|
|
|
+TexGrid::TexGrid(MandelView& owner, int level) :
|
|
|
owner{ owner },
|
|
|
level{ level },
|
|
|
dpp{ owner.getDpp(level) }
|
|
@@ -166,13 +168,13 @@ TexGrid::TexGrid(MandelV& owner, int level) :
|
|
|
|
|
|
std::pair<GridIndex, GridIndex> TexGrid::getCellIndices(double x, double y)
|
|
|
{
|
|
|
- return { ::floor(x / dpp / MandelV::chunkSize), ::floor(y / dpp / MandelV::chunkSize) };
|
|
|
+ return { ::floor(x / dpp / MandelView::chunkSize), ::floor(y / dpp / MandelView::chunkSize) };
|
|
|
}
|
|
|
|
|
|
|
|
|
std::pair<double, double> TexGrid::getPositions(GridIndex x, GridIndex y)
|
|
|
{
|
|
|
- return { x * dpp * MandelV::chunkSize, y * dpp * MandelV::chunkSize };
|
|
|
+ return { x * dpp * MandelView::chunkSize, y * dpp * MandelView::chunkSize };
|
|
|
}
|
|
|
|
|
|
|
|
@@ -203,14 +205,14 @@ void TexGrid::clearCells(void)
|
|
|
void Job::run(void)
|
|
|
{
|
|
|
auto [absX, absY] = grid->getPositions(i, j);
|
|
|
- double gw = grid->dpp * MandelV::chunkSize;
|
|
|
+ double gw = grid->dpp * MandelView::chunkSize;
|
|
|
|
|
|
- Bitmap<float> f(MandelV::chunkSize, MandelV::chunkSize);
|
|
|
+ Bitmap<float> f(MandelView::chunkSize, MandelView::chunkSize);
|
|
|
mnd::MandelInfo mi;
|
|
|
mi.view.x = absX;
|
|
|
mi.view.y = absY;
|
|
|
mi.view.width = mi.view.height = gw;
|
|
|
- mi.bWidth = mi.bHeight = MandelV::chunkSize;
|
|
|
+ mi.bWidth = mi.bHeight = MandelView::chunkSize;
|
|
|
mi.maxIter = maxIter;
|
|
|
mndContext.getDefaultGenerator().generate(mi, f.pixels.get());
|
|
|
auto* rgb = new Bitmap<RGBColor>(f.map<RGBColor>([&mi, this](float i) {
|
|
@@ -286,7 +288,7 @@ void Calcer::redirect(int level, GridIndex i, GridIndex j, Bitmap<RGBColor>* bmp
|
|
|
}
|
|
|
|
|
|
|
|
|
-MandelV::MandelV(mnd::MandelContext& mndContext, Gradient& gradient, int maxIter) :
|
|
|
+MandelView::MandelView(mnd::MandelContext& mndContext, Gradient& gradient, int maxIter) :
|
|
|
mndContext{ mndContext },
|
|
|
calcer{ mndContext, gradient, maxIter },
|
|
|
gradient{ gradient },
|
|
@@ -304,22 +306,22 @@ MandelV::MandelV(mnd::MandelContext& mndContext, Gradient& gradient, int maxIter
|
|
|
}
|
|
|
}
|
|
|
empty = std::make_unique<Texture>(emp, GL_NEAREST);
|
|
|
- connect(&calcer, &Calcer::done, this, &MandelV::cellReady);
|
|
|
+ connect(&calcer, &Calcer::done, this, &MandelView::cellReady);
|
|
|
}
|
|
|
|
|
|
|
|
|
-int MandelV::getLevel(double dpp) {
|
|
|
+int MandelView::getLevel(double dpp) {
|
|
|
return int(::log2(dpp / chunkSize));
|
|
|
}
|
|
|
|
|
|
|
|
|
-double MandelV::getDpp(int level)
|
|
|
+double MandelView::getDpp(int level)
|
|
|
{
|
|
|
return ::pow(2, level) * chunkSize;
|
|
|
}
|
|
|
|
|
|
|
|
|
-TexGrid& MandelV::getGrid(int level)
|
|
|
+TexGrid& MandelView::getGrid(int level)
|
|
|
{
|
|
|
auto it = levels.find(level);
|
|
|
if (it != levels.end()) {
|
|
@@ -332,17 +334,17 @@ TexGrid& MandelV::getGrid(int level)
|
|
|
}
|
|
|
|
|
|
|
|
|
-void MandelV::setMaxIter(int maxIter)
|
|
|
+void MandelView::setMaxIter(int maxIter)
|
|
|
{
|
|
|
this->maxIter = maxIter;
|
|
|
calcer.setMaxIter(maxIter);
|
|
|
- clear();
|
|
|
+ clearCells();
|
|
|
emit redrawRequested();
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-void MandelV::clear(void)
|
|
|
+void MandelView::clearCells(void)
|
|
|
{
|
|
|
for(auto& [level, grid] : this->levels) {
|
|
|
grid.clearCells();
|
|
@@ -350,7 +352,7 @@ void MandelV::clear(void)
|
|
|
}
|
|
|
|
|
|
|
|
|
-void MandelV::garbageCollect(int level, GridIndex i, GridIndex j)
|
|
|
+void MandelView::garbageCollect(int level, GridIndex i, GridIndex j)
|
|
|
{
|
|
|
for(auto& [l, grid] : levels) {
|
|
|
int dist = ::abs(l - level);
|
|
@@ -378,7 +380,7 @@ void MandelV::garbageCollect(int level, GridIndex i, GridIndex j)
|
|
|
}
|
|
|
|
|
|
|
|
|
-GridElement* MandelV::searchAbove(int level, GridIndex i, GridIndex j, int recursionLevel)
|
|
|
+GridElement* MandelView::searchAbove(int level, GridIndex i, GridIndex j, int recursionLevel)
|
|
|
{
|
|
|
auto& grid = getGrid(level);
|
|
|
auto& gridAbove = getGrid(level + 1);
|
|
@@ -408,7 +410,7 @@ GridElement* MandelV::searchAbove(int level, GridIndex i, GridIndex j, int recur
|
|
|
}
|
|
|
|
|
|
|
|
|
-GridElement* MandelV::searchUnder(int level, GridIndex i, GridIndex j, int recursionLevel)
|
|
|
+GridElement* MandelView::searchUnder(int level, GridIndex i, GridIndex j, int recursionLevel)
|
|
|
{
|
|
|
if (recursionLevel == 0)
|
|
|
return nullptr;
|
|
@@ -451,7 +453,7 @@ GridElement* MandelV::searchUnder(int level, GridIndex i, GridIndex j, int recur
|
|
|
}
|
|
|
|
|
|
|
|
|
-void MandelV::paint(const mnd::MandelViewport& mvp)
|
|
|
+void MandelView::paint(const mnd::MandelViewport& mvp)
|
|
|
{
|
|
|
double dpp = mvp.width / width;
|
|
|
int level = getLevel(dpp) - 1;
|
|
@@ -509,7 +511,7 @@ void MandelV::paint(const mnd::MandelViewport& mvp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void MandelV::cellReady(int level, GridIndex i, GridIndex j, Bitmap<RGBColor>* bmp)
|
|
|
+void MandelView::cellReady(int level, GridIndex i, GridIndex j, Bitmap<RGBColor>* bmp)
|
|
|
{
|
|
|
|
|
|
this->getGrid(level).setCell(i, j,
|
|
@@ -547,6 +549,14 @@ MandelWidget::~MandelWidget()
|
|
|
}
|
|
|
|
|
|
|
|
|
+void MandelWidget::setGradient(Gradient g)
|
|
|
+{
|
|
|
+ this->gradient = std::move(g);
|
|
|
+ this->mandelView->clearCells();
|
|
|
+ emit update();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void MandelWidget::initializeGL(void)
|
|
|
{
|
|
|
this->context()->functions()->glClearColor(0, 0, 0, 0);
|
|
@@ -559,22 +569,22 @@ void MandelWidget::initializeGL(void)
|
|
|
|
|
|
//glShadeModel(GL_SMOOTH);
|
|
|
|
|
|
- v = nullptr;
|
|
|
+ mandelView = nullptr;
|
|
|
requestRecalc();
|
|
|
}
|
|
|
|
|
|
|
|
|
void MandelWidget::paintGL(void)
|
|
|
{
|
|
|
- if (v == nullptr) {
|
|
|
- v = std::make_unique<MandelV>(mndContext, gradient, maxIterations);
|
|
|
- QObject::connect(v.get(), &MandelV::redrawRequested, this, static_cast<void(QOpenGLWidget::*)(void)>(&QOpenGLWidget::update));
|
|
|
+ if (mandelView == nullptr) {
|
|
|
+ mandelView = std::make_unique<MandelView>(mndContext, gradient, maxIterations);
|
|
|
+ QObject::connect(mandelView.get(), &MandelView::redrawRequested, this, static_cast<void(QOpenGLWidget::*)(void)>(&QOpenGLWidget::update));
|
|
|
}
|
|
|
|
|
|
int width = this->width();
|
|
|
int height = this->height();
|
|
|
- v->width = width;
|
|
|
- v->height = height;
|
|
|
+ mandelView->width = width;
|
|
|
+ mandelView->height = height;
|
|
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
|
@@ -591,7 +601,7 @@ void MandelWidget::paintGL(void)
|
|
|
glLoadIdentity();
|
|
|
|
|
|
updateAnimations();
|
|
|
- v->paint(this->currentViewport);
|
|
|
+ mandelView->paint(this->currentViewport);
|
|
|
|
|
|
if (rubberbanding)
|
|
|
drawRubberband();
|
|
@@ -656,41 +666,24 @@ void MandelWidget::zoom(float scale, float x, float y)
|
|
|
void MandelWidget::setMaxIterations(int maxIter)
|
|
|
{
|
|
|
this->maxIterations = maxIter;
|
|
|
- if (v)
|
|
|
- v->setMaxIter(maxIter);
|
|
|
+ if (mandelView)
|
|
|
+ mandelView->setMaxIter(maxIter);
|
|
|
requestRecalc();
|
|
|
}
|
|
|
|
|
|
|
|
|
void MandelWidget::requestRecalc()
|
|
|
{
|
|
|
- //emit needsUpdate(MandelInfo{ viewport, this->width(), this->height(), maxIterations });
|
|
|
- this->update();
|
|
|
+ emit update();
|
|
|
}
|
|
|
|
|
|
|
|
|
void MandelWidget::resizeGL(int width, int height)
|
|
|
{
|
|
|
- //glViewport(0, 0, (GLint) width, (GLint) height);
|
|
|
- this->update();
|
|
|
+ emit update();
|
|
|
}
|
|
|
|
|
|
|
|
|
-/*void MandelWidget::redraw(void)
|
|
|
-{
|
|
|
- /*CpuGenerator<double> cpg;
|
|
|
- MandelInfo mi;
|
|
|
- mi.bWidth = this->geometry().width();//ql.geometry().width();
|
|
|
- mi.bHeight = this->geometry().height(); //ql.geometry().height();
|
|
|
- mi.maxIter = 250;
|
|
|
- mi.view = viewport;*/
|
|
|
- //update();
|
|
|
- //emit needsUpdate(viewport);
|
|
|
-
|
|
|
- //auto bitmap = cpg.generate(mi).map<uint32_t>([](RGBColor rgb) { return 255 << 24 | rgb.b << 16 | rgb.g << 8 | rgb.r; });
|
|
|
-//}
|
|
|
-
|
|
|
-
|
|
|
void MandelWidget::resizeEvent(QResizeEvent* re)
|
|
|
{
|
|
|
QOpenGLWidget::resizeEvent(re);
|
|
@@ -702,9 +695,9 @@ void MandelWidget::resizeEvent(QResizeEvent* re)
|
|
|
//else
|
|
|
// viewport.width = (viewport.height * aspect);
|
|
|
|
|
|
- if (v.get() != nullptr) {
|
|
|
- v->width = this->width();
|
|
|
- v->height = this->height();
|
|
|
+ if (mandelView.get() != nullptr) {
|
|
|
+ mandelView->width = this->width();
|
|
|
+ mandelView->height = this->height();
|
|
|
}
|
|
|
//printf("resized\n");
|
|
|
requestRecalc();
|
|
@@ -785,9 +778,11 @@ void MandelWidget::wheelEvent(QWheelEvent* we)
|
|
|
QOpenGLWidget::wheelEvent(we);
|
|
|
float x = float(we->x()) / this->width();
|
|
|
float y = float(we->y()) / this->height();
|
|
|
- float scale = ::pow(0.9975, we->angleDelta().y());
|
|
|
+ float scale = ::powf(0.9975f, we->angleDelta().y());
|
|
|
//printf("scale: %f\n", double(scale));
|
|
|
zoom(scale, x, y);
|
|
|
+ if (!we->pixelDelta().isNull())
|
|
|
+ this->currentViewport = this->targetViewport;
|
|
|
we->accept();
|
|
|
}
|
|
|
|