Working on adding mouse-panning and zoom.
This commit is contained in:
@@ -35,6 +35,7 @@ enum class Fractal {
|
|||||||
MandelbrotSet, JuliaSet
|
MandelbrotSet, JuliaSet
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This class represents the FractalApp program state.
|
||||||
class FractalInspectorApp : public ReWindow::OpenGLWindow {
|
class FractalInspectorApp : public ReWindow::OpenGLWindow {
|
||||||
protected:
|
protected:
|
||||||
JUI::Scene *scene;
|
JUI::Scene *scene;
|
||||||
@@ -59,10 +60,13 @@ protected:
|
|||||||
Color4 u_rgb_4 = Colors::Green;
|
Color4 u_rgb_4 = Colors::Green;
|
||||||
Vector2 u_julia_set {0,0};
|
Vector2 u_julia_set {0,0};
|
||||||
Vector2 u_julia_value {0,0};
|
Vector2 u_julia_value {0,0};
|
||||||
|
bool panning = false;
|
||||||
|
|
||||||
Fractal current_fractal = Fractal::MandelbrotSet;
|
Fractal current_fractal = Fractal::MandelbrotSet;
|
||||||
|
|
||||||
|
void OnShaderLoadFail(const std::string&, const std::string&);
|
||||||
public:
|
public:
|
||||||
FractalInspectorApp();
|
FractalInspectorApp(int width, int height);
|
||||||
|
|
||||||
/// Returns a full-path file name for a GLSL vertex shader, from a given prefix name.
|
/// 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);
|
static std::filesystem::path VertexShaderFilepathFromPrefixName(const std::string &name);
|
||||||
@@ -101,6 +105,8 @@ public:
|
|||||||
/// Performs a logic update.
|
/// Performs a logic update.
|
||||||
void Update(float elapsed);
|
void Update(float elapsed);
|
||||||
|
|
||||||
|
float ReadableScale();
|
||||||
|
|
||||||
/// Pushes updated shader paramters to the OpenGL shader program.
|
/// Pushes updated shader paramters to the OpenGL shader program.
|
||||||
void UpdateShaderUniforms(float elapsed);
|
void UpdateShaderUniforms(float elapsed);
|
||||||
|
|
||||||
|
7
main.cpp
7
main.cpp
@@ -11,7 +11,12 @@
|
|||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
ReWindow::Logger::Debug.EnableConsole(false);
|
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->Open();
|
||||||
program->SetFullscreen(false);
|
program->SetFullscreen(false);
|
||||||
|
@@ -68,6 +68,9 @@ float iterate_mandelbrot(vec2 p) {
|
|||||||
void main() {
|
void main() {
|
||||||
vec2 R = u_resolution.xy;
|
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;
|
vec2 uv = (u_scale * gl_FragCoord.xy - R - 1.) / R.y - u_translation;
|
||||||
|
|
||||||
float n = iterate_mandelbrot(uv) / N;
|
float n = iterate_mandelbrot(uv) / N;
|
||||||
|
@@ -1,15 +1,21 @@
|
|||||||
#include <FractalApp.hpp>
|
#include <FractalApp.hpp>
|
||||||
|
|
||||||
FractalInspectorApp::FractalInspectorApp(): ReWindow::OpenGLWindow("ReShader", 1800, 1000, 2, 1) {
|
#define GL_VER_MAJOR 2
|
||||||
Shader::OnCompilationErrorMessage += [this](std::string type, std::string infoLog) {
|
#define GL_VER_MINOR 1
|
||||||
auto log_lines = misc::string_expand(infoLog, '\n');
|
|
||||||
console->Log(type, Colors::Red);
|
void FractalInspectorApp::OnShaderLoadFail(const std::string& type, const std::string& infoLog) {
|
||||||
std::cerr << type << std::endl;
|
auto log_lines = misc::string_expand(infoLog, '\n');
|
||||||
for (auto line: log_lines) {
|
console->Log(type, Colors::Red);
|
||||||
console->Log(line, Colors::Red);
|
std::cerr << type << std::endl;
|
||||||
std::cerr << line << std::endl;
|
for (auto line: log_lines) {
|
||||||
}
|
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;
|
u_time = 0;
|
||||||
}
|
}
|
||||||
@@ -439,11 +445,20 @@ void FractalInspectorApp::Update(float elapsed) {
|
|||||||
|
|
||||||
int fps = 1.f / 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);
|
fps_label->SetContent(fps_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float FractalInspectorApp::ReadableScale() {
|
||||||
|
return 3.f - u_scale;
|
||||||
|
}
|
||||||
|
|
||||||
void FractalInspectorApp::UpdateShaderUniforms(float elapsed) {
|
void FractalInspectorApp::UpdateShaderUniforms(float elapsed) {
|
||||||
Vector2 u_res = Vector2(GetSize().x, GetSize().y);
|
Vector2 u_res = Vector2(GetSize().x, GetSize().y);
|
||||||
|
|
||||||
@@ -507,27 +522,71 @@ void FractalInspectorApp::OnRefresh(float elapsed) {
|
|||||||
this->SwapBuffers();
|
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) {
|
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);
|
scene->ObserveMouseInput(JUI::MouseButton::Left, true);
|
||||||
if (e.Button == MouseButtons::Middle)
|
if (e.Button == MouseButtons::Middle)
|
||||||
scene->ObserveMouseInput(JUI::MouseButton::Middle, true);
|
scene->ObserveMouseInput(JUI::MouseButton::Middle, true);
|
||||||
if (e.Button == MouseButtons::Right)
|
if (e.Button == MouseButtons::Right)
|
||||||
scene->ObserveMouseInput(JUI::MouseButton::Right, true);
|
scene->ObserveMouseInput(JUI::MouseButton::Right, true);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void FractalInspectorApp::OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &e) {
|
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);
|
scene->ObserveMouseInput(JUI::MouseButton::Left, false);
|
||||||
if (e.Button == MouseButtons::Middle)
|
if (e.Button == MouseButtons::Middle)
|
||||||
scene->ObserveMouseInput(JUI::MouseButton::Middle, false);
|
scene->ObserveMouseInput(JUI::MouseButton::Middle, false);
|
||||||
if (e.Button == MouseButtons::Right)
|
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) {
|
void FractalInspectorApp::OnMouseMove(const ReWindow::MouseMoveEvent &e) {
|
||||||
Vector2 nmp = Vector2(e.Position.x, e.Position.y);
|
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) {
|
void FractalInspectorApp::OnKeyDown(const ReWindow::KeyDownEvent &e) {
|
||||||
|
Reference in New Issue
Block a user