#include "FractalView.h"
#include "AUI/Render/IRenderer.h"
#include <glm/gtc/matrix_transform.hpp>
FractalView::FractalView() : mTransform(1.f) {
setExpanding();
mShader.load(
"in vec4 pos;"
"in vec2 uv;"
"out vec2 pass_uv;"
"uniform float ratio;"
"uniform mat4 SL_uniform_transform;"
"void main() {"
"gl_Position = SL_uniform_transform * pos;"
"pass_uv = (uv - 0.5) * 2.0;"
"pass_uv.x *= ratio;"
"}",
"in vec2 pass_uv;\n"
"#define product(a, b) dvec2(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x)\n"
"#define conjugate(a) dvec2(a.x,-a.y)\n"
"#define divide(a, b) dvec2(((a.x*b.x+a.y*b.y)/(b.x*b.x+b.y*b.y)),((a.y*b.x-a.x*b.y)/(b.x*b.x+b.y*b.y)))\n"
"uniform float c;"
"uniform int iterations;"
"uniform dmat4 tr;"
"uniform sampler2D tex;"
"out vec4 color;"
"void main() {"
"dvec2 tmp_pass_uv = (tr * dvec4(pass_uv, 0.0, 1.0)).xy;"
"dvec2 v = dvec2(0, 0);"
"int i = 0;"
"for (; i < iterations; ++i) {"
"v = product(v, v) + tmp_pass_uv;"
"dvec2 tmp = v * v;"
"if ((v.x + v.y) > 4) {"
"break;"
"}"
"}"
"if (i == iterations) {"
"color = vec4(0, 0, 0, 1);"
"} else {"
"float theta = float(i) / float(iterations);"
"color = texture(tex, vec2(theta, 0));"
"}"
"}",
{ "pos", "uv" }, "400");
mShader.compile();
mShader.use();
mShader.set(UNIFORM_TR, mTransform);
mShader.set(UNIFORM_SQ, 1.f);
mTexture = _new<gl::Texture2D>();
mTexture->tex2D(*AImage::fromUrl(":img/color_scheme_wikipedia.png"));
}
mShader.use();
mTexture->bind();
}
void FractalView::setSize(glm::ivec2 size) {
AView::setSize(size);
mShader.use();
mShader.set(UNIFORM_RATIO, mAspectRatio = float(size.x) / float(size.y));
}
void FractalView::setIterations(unsigned it) {
mShader.use();
mShader.set(UNIFORM_ITERATIONS, int(it));
}
auto projectedPos = (glm::dvec2(event.
origin) / glm::dvec2(getSize()) - glm::dvec2(0.5)) * 2.0;
projectedPos.x *= mAspectRatio;
mTransform = glm::translate(mTransform, glm::dvec3 { projectedPos, 0.0 });
mTransform = glm::scale(mTransform, glm::dvec3(1.0 - event.
delta.y / 1000.0));
mTransform = glm::translate(mTransform, -glm::dvec3 { projectedPos, 0.0 });
handleMatrixUpdated();
redraw();
}
void FractalView::reset() {
mTransform = glm::dmat4(1.0);
handleMatrixUpdated();
redraw();
}
void FractalView::handleMatrixUpdated() {
mShader.use();
mShader.set(UNIFORM_TR, mTransform);
emit centerPosChanged(getPlotPosition(), getPlotScale());
}
void FractalView::onKeyDown(AInput::Key key) {
AView::onKeyDown(key);
onKeyRepeat(key);
}
void FractalView::onKeyRepeat(AInput::Key key) {
AView::onKeyRepeat(key);
constexpr float SPEED = 0.2f;
switch (key) {
case AInput::UP:
mTransform = glm::translate(mTransform, { 0, -SPEED, 0 });
break;
case AInput::DOWN:
mTransform = glm::translate(mTransform, { 0, SPEED, 0 });
break;
case AInput::LEFT:
mTransform = glm::translate(mTransform, { -SPEED, 0, 0 });
break;
case AInput::RIGHT:
mTransform = glm::translate(mTransform, { SPEED, 0, 0 });
break;
case AInput::PAGEDOWN:
mTransform = glm::scale(mTransform, glm::dvec3 { 0.99 });
break;
case AInput::PAGEUP:
mTransform = glm::scale(mTransform, glm::dvec3 { 1.01 });
break;
default:
return;
}
handleMatrixUpdated();
}
glm::dvec2 FractalView::getPlotPosition() const { return glm::dvec2(mTransform[3]); }
double FractalView::getPlotScale() const { return mTransform[0][0]; }
void FractalView::setPlotPositionAndScale(glm::dvec2 position, double scale) {
mTransform = glm::dmat4(scale);
mTransform[3] = glm::dvec4 { position, 0, 1 };
handleMatrixUpdated();
}
virtual void render(ARenderContext ctx)
Draws this AView. Noone should call this function except rendering routine.
virtual void onScroll(const AScrollEvent &event)
virtual void rectangle(const ABrush &brush, glm::vec2 position, glm::vec2 size)=0
Draws simple rectangle.
#define emit
emits the specified signal in context of this object.
Definition AObject.h:343
Render context passed to AView::render.
Definition ARenderContext.h:43