Working on adding mouse-panning and zoom.

This commit is contained in:
2025-05-08 08:21:47 -05:00
parent 7016c4f315
commit c648750932
4 changed files with 91 additions and 18 deletions

View File

@@ -35,6 +35,7 @@ enum class Fractal {
MandelbrotSet, JuliaSet
};
/// This class represents the FractalApp program state.
class FractalInspectorApp : public ReWindow::OpenGLWindow {
protected:
JUI::Scene *scene;
@@ -59,10 +60,13 @@ protected:
Color4 u_rgb_4 = Colors::Green;
Vector2 u_julia_set {0,0};
Vector2 u_julia_value {0,0};
bool panning = false;
Fractal current_fractal = Fractal::MandelbrotSet;
void OnShaderLoadFail(const std::string&, const std::string&);
public:
FractalInspectorApp();
FractalInspectorApp(int width, int height);
/// Returns a full-path file name for a GLSL vertex shader, from a given prefix name.
static std::filesystem::path VertexShaderFilepathFromPrefixName(const std::string &name);
@@ -101,6 +105,8 @@ public:
/// Performs a logic update.
void Update(float elapsed);
float ReadableScale();
/// Pushes updated shader paramters to the OpenGL shader program.
void UpdateShaderUniforms(float elapsed);

View File

@@ -11,7 +11,12 @@
int main(int argc, char** argv) {
ReWindow::Logger::Debug.EnableConsole(false);
auto* program = new FractalInspectorApp();
int default_app_width = 1080;
int default_app_height = 768;
// TODO: Create AppConfig struct and pass to constructor.
auto* program = new FractalInspectorApp(default_app_width, default_app_height);
program->Open();
program->SetFullscreen(false);

View File

@@ -68,6 +68,9 @@ float iterate_mandelbrot(vec2 p) {
void main() {
vec2 R = u_resolution.xy;
// Unused as of yet, see TODOs for what and why.
float scale = (3.0 - u_scale);
vec2 uv = (u_scale * gl_FragCoord.xy - R - 1.) / R.y - u_translation;
float n = iterate_mandelbrot(uv) / N;

View File

@@ -1,7 +1,9 @@
#include <FractalApp.hpp>
FractalInspectorApp::FractalInspectorApp(): ReWindow::OpenGLWindow("ReShader", 1800, 1000, 2, 1) {
Shader::OnCompilationErrorMessage += [this](std::string type, std::string infoLog) {
#define GL_VER_MAJOR 2
#define GL_VER_MINOR 1
void FractalInspectorApp::OnShaderLoadFail(const std::string& type, const std::string& infoLog) {
auto log_lines = misc::string_expand(infoLog, '\n');
console->Log(type, Colors::Red);
std::cerr << type << std::endl;
@@ -9,7 +11,11 @@ FractalInspectorApp::FractalInspectorApp(): ReWindow::OpenGLWindow("ReShader", 1
console->Log(line, Colors::Red);
std::cerr << line << std::endl;
}
};
}
FractalInspectorApp::FractalInspectorApp(int width, int height):
OpenGLWindow("FractalInspector",width, height, GL_VER_MAJOR, GL_VER_MINOR) {
Shader::OnCompilationErrorMessage += [this] (auto... args) { OnShaderLoadFail(args...);};
u_time = 0;
}
@@ -439,11 +445,20 @@ void FractalInspectorApp::Update(float elapsed) {
int fps = 1.f / elapsed;
std::string fps_text = std::format("FPS: {}", fps);
// TODO: Consider moving this logic deeper into the shader to make it easier to work with.
float readable_scale = Math::Round(ReadableScale(), 3);
std::string fps_text = std::format("Pos: {},{} Zoom: {}x FPS: {}",
Math::Round(u_translation.x, 2), Math::Round(u_translation.y, 2), readable_scale, fps);
fps_label->SetContent(fps_text);
}
float FractalInspectorApp::ReadableScale() {
return 3.f - u_scale;
}
void FractalInspectorApp::UpdateShaderUniforms(float elapsed) {
Vector2 u_res = Vector2(GetSize().x, GetSize().y);
@@ -507,27 +522,71 @@ void FractalInspectorApp::OnRefresh(float elapsed) {
this->SwapBuffers();
}
enum JUI::MouseButton ToJUIEnum(const MouseButton& btn) {
if (btn == MouseButtons::Left) return JUI::MouseButton::Left;
if (btn == MouseButtons::Middle) return JUI::MouseButton::Middle;
if (btn == MouseButtons::Right) return JUI::MouseButton::Right;
// Default condition.
return JUI::MouseButton::Left;
}
void FractalInspectorApp::OnMouseButtonDown(const ReWindow::MouseButtonDownEvent &e) {
if (e.Button == MouseButtons::Left)
auto btn = ToJUIEnum(e.Button);
if (scene->ObserveMouseInput(btn, true))
return;
if (btn == JUI::MouseButton::Right)
panning = true;
/*if (e.Button == MouseButtons::Left)
scene->ObserveMouseInput(JUI::MouseButton::Left, true);
if (e.Button == MouseButtons::Middle)
scene->ObserveMouseInput(JUI::MouseButton::Middle, true);
if (e.Button == MouseButtons::Right)
scene->ObserveMouseInput(JUI::MouseButton::Right, true);
scene->ObserveMouseInput(JUI::MouseButton::Right, true);*/
}
void FractalInspectorApp::OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &e) {
if (e.Button == MouseButtons::Left)
auto btn = ToJUIEnum(e.Button);
if (scene->ObserveMouseInput(btn, true))
return;
if (btn == JUI::MouseButton::Right)
panning = false;
/*if (e.Button == MouseButtons::Left)
scene->ObserveMouseInput(JUI::MouseButton::Left, false);
if (e.Button == MouseButtons::Middle)
scene->ObserveMouseInput(JUI::MouseButton::Middle, false);
if (e.Button == MouseButtons::Right)
scene->ObserveMouseInput(JUI::MouseButton::Right, false);
scene->ObserveMouseInput(JUI::MouseButton::Right, false);*/
}
Vector2 last{0,0};
void FractalInspectorApp::OnMouseMove(const ReWindow::MouseMoveEvent &e) {
Vector2 nmp = Vector2(e.Position.x, e.Position.y);
scene->ObserveMouseMovement(nmp);
if (scene->ObserveMouseMovement(nmp))
return;
// TODO: e.Delta is always 0, investigate in JUI.
Vector2 delta = nmp - last;
float bias_slowdown_as_we_zoom_in = 1.125f;
float base_slowdown = 0.005;
if (panning)
u_translation += delta*(1.f / ReadableScale()*bias_slowdown_as_we_zoom_in)*base_slowdown;
last = nmp;
}
void FractalInspectorApp::OnKeyDown(const ReWindow::KeyDownEvent &e) {