6 Commits

6 changed files with 140 additions and 18 deletions

View File

@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.18..3.30)
cmake_minimum_required(VERSION 3.18..3.29)
project(FractalInspector
VERSION 1.0
VERSION 1.1
LANGUAGES CXX)
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
@@ -15,7 +15,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(cmake/CPM.cmake)
CPMAddPackage(NAME mcolor
URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-7.3.zip)
URL https://git.redacted.cc/maxine/mcolor/archive/Release-1.zip)
CPMAddPackage(NAME jlog
URL https://git.redacted.cc/josh/jlog/archive/Prerelease-18.zip)
@@ -35,14 +35,20 @@ CPMAddPackage(NAME JGL
CPMAddPackage(NAME JUI
URL https://git.redacted.cc/josh/ReJUI/archive/Prerelease-6.zip)
#file(COPY "assets" DESTINATION "${PROJECT_BINARY_DIR}")
file(COPY "shaders" DESTINATION "${PROJECT_BINARY_DIR}")
#file(GLOB_RECURSE ASSETS "assets/")
file(GLOB_RECURSE HEADERS "include/*.h" "include/*.hpp")
file(GLOB_RECURSE SOURCES "src/*.c" "src/*.cpp")
include_directories(${PROJECT_SOURCE_DIR}/include)
add_executable(FractalInspector main.cpp ${SOURCES})
if (WIN32)
add_executable(FractalInspector main.cpp ${SOURCES} app.rc)
endif()
if (UNIX)
add_executable(FractalInspector main.cpp ${SOURCES})
endif()
target_include_directories(FractalInspector PUBLIC ${Event_SOURCE_DIR}/include)
target_include_directories(FractalInspector PUBLIC ${J3ML_SOURCE_DIR}/include)

4
app.rc Normal file
View File

@@ -0,0 +1,4 @@
MAINICON ICON "icon.ico"
IDI_ICON1 ICON DISCARDABLE "icon.ico"
MANIFEST ICON "icon.ico"
AAA ICON "icon.ico"

View File

@@ -51,6 +51,8 @@ inline void Lerped<float>::Update(float elapsed) { current = Math::Lerp(current,
template <>
inline void Lerped<Vector2>::Update(float elapsed) { current = Vector2::Lerp(current, goal, elapsed*rate); }
/// This class represents the FractalApp program state.
class FractalInspectorApp : public ReWindow::OpenGLWindow {
protected:
@@ -67,6 +69,12 @@ protected:
JGL::Shader mandelbrot_shader;
JGL::Shader julia_shader;
JGL::RenderTarget *canvas;
JUI::Slider* julia_x_slider;
JUI::Slider* julia_y_slider;
JUI::Text* julia_x_label;
JUI::Text* julia_y_label;
float u_time;
float u_scale = 2.f;
float u_scale_goal = 2.f;
@@ -122,6 +130,23 @@ public:
/// Passes the current window size to subordinate objects, such as the JUI scene.
void PropagateWindowSize();
Vector2 FractalSpaceToScreenSpace(const Vector2& pos) {
Vector2 R(GetWidth(), GetHeight());
Vector2 translation(u_translation.x, -u_translation.y);
return ((pos + u_translation) * R.y + R + Vector2(1.f, 1.f)) / u_scale;
}
Vector2 ScreenSpaceToFractalSpace(const Vector2& pos) {
Vector2 tpos = -pos;
Vector2 R(GetWidth(), GetHeight());
Vector2 scaled = pos * u_scale;
Vector2 translation(u_translation.x, -u_translation.y);
Vector2 uv = ((scaled - R - Vector2(1.f, 1.f)) / R.y) - u_translation;
return uv;
}
void ZoomIn(float rate);
void ZoomInTowards(const Vector2 &dir, float rate);
@@ -179,7 +204,6 @@ public:
}
void TakeScreenshot();
protected:
private:
};

View File

@@ -8,9 +8,10 @@
// TODO: Parse command-line args.
int main(int argc, char** argv) {
mcolor::windowsSaneify();
ReWindow::Logger::Debug.EnableConsole(false);
int default_app_width = 1660;
int default_app_width = 1440;
int default_app_height = 900;
// TODO: Create AppConfig struct and pass to constructor.

View File

@@ -24,7 +24,7 @@ uniform vec3 u_rgb_3;
uniform vec3 u_rgb_4;
#define N 256. // Number of iterations?
#define B 4. // What does B mean?
#define B 8. // What does B mean?
// The mandelbrot set is a set of complex numbers c for which the function:
// f(z) = z*z + c
@@ -38,8 +38,8 @@ float iterate_mandelbrot(vec2 p) {
for (i=0.; i < N; i++ ) {
// This line performs the core Mandelbrot iteration: z = z^2 + c.
// It is done using a matrix multiplication to perform the complex number squaring.
// If z = x + iy, then z&2 = (i+iy)(x+iy) = x^2 - y ^ 2 + 2ixy.
// The matrix [x, -y; y, x] multiplied by [x, y] gives [x*x - y&y, y*x + x*y] = [Re(z^2) Im(z^2)].
// If z = x + iy, then z&2 = (x+iy)(x+iy) = x^2 - y ^ 2 + 2ixy.
// The matrix [x, -y; y, x] multiplied by [x, y] gives [x*x - y*y, y*x + x*y] = [Re(z^2) Im(z^2)].
// Then we add the constant complex number c (represented by the input vec2).
z = mat2(z, -z.y, z.x) * z + c;

View File

@@ -20,11 +20,11 @@ FractalInspectorApp::FractalInspectorApp(int width, int height):
}
std::filesystem::path FractalInspectorApp::VertexShaderFilepathFromPrefixName(const std::string &name) {
return "../shaders/" + name + ".vert.glsl";
return "shaders/" + name + ".vert.glsl";
}
std::filesystem::path FractalInspectorApp::FragmentShaderFilepathFromPrefixName(const std::string &name) {
return "../shaders/" + name + ".frag.glsl";
return "shaders/" + name + ".frag.glsl";
}
void FractalInspectorApp::LoadShaders() {
@@ -105,6 +105,16 @@ void FractalInspectorApp::UnloadJulia() {
juliaset_dialog->Close();
}
// Tested and works on both platform, but is a security **NIGHTMARE**.
void OpenURL(const std::string &url) {
#ifdef _WIN32
system(std::format("start {}", url).c_str());
#endif
#ifdef linux
system(std::format("xdg-open {}", url).c_str());
#endif
}
JUI::Window * FractalInspectorApp::CreateAppInfoDialogWindow(JUI::Widget *parent) {
// TODO: Implement JUI structure that makes blocks of text easy to impelement.
auto window = new JUI::Window(parent);
@@ -112,6 +122,8 @@ JUI::Window * FractalInspectorApp::CreateAppInfoDialogWindow(JUI::Widget *parent
window->Size({300_px, 375_px});
window->MinSize({300, 375});
window->Position({100_percent - 325_px, 100_percent - 400_px});
auto* layout = new JUI::VerticalListLayout(window->Content());
layout->Padding(0_px);
@@ -156,18 +168,23 @@ JUI::Window * FractalInspectorApp::CreateAppInfoDialogWindow(JUI::Widget *parent
auto* btn_layout = new JUI::HorizontalListLayout(btn_box);
btn_layout->Padding(8_px);
auto btn_item = [&] (const std::string& text) -> JUI::TextButton* {
auto btn_item = [&] (const std::string& text, const std::function<void()>& callback = {}) -> JUI::TextButton* {
JUI::TextButton* btn = new JUI::TextButton(btn_layout);
btn->SetContent(text);
btn->Size({32_percent, 100_percent});
btn->SetTextColor(Colors::Black);
btn->Center();
btn->OnClickEvent += [callback] (auto a, auto b) {
callback();
};
return btn;
};
auto* btn_a = btn_item("License");
auto* btn_b = btn_item("Wiki");
auto* btn_c = btn_item("Source");
auto* btn_c = btn_item("Source", []() {
OpenURL("https://git.redacted.cc/josh/FractalInspector");
});
return window;
@@ -239,8 +256,8 @@ void FractalInspectorApp::CreateMenu() {
// TODO: Utilize for things later.
colorpicker_window = new JUI::Window(scene);
colorpicker_window->SetTitle("Color-Pickers");
colorpicker_window->MinSize({600, 150});
colorpicker_window->Size({600_px, 150_px});
colorpicker_window->MinSize({300, 150});
colorpicker_window->Size({400_px, 150_px});
colorpicker_window->Position({50_px, 50_px});
auto* col_layout = new JUI::HorizontalListLayout(colorpicker_window->Content());
@@ -285,6 +302,7 @@ void FractalInspectorApp::CreateMenu() {
console->OnInput += [this] (const std::string& message) {
ParseCmdLineMessage(message);
};
console->Close();
mandelbrotset_dialog = new JUI::Window(scene);
@@ -340,21 +358,36 @@ void FractalInspectorApp::CreateMenu() {
juliaset_dialog->Size({900_px, 70_px});
juliaset_dialog->Close(); // Defaults to close.
auto* julia_x_slider = new JUI::Slider(juliaset_dialog->Content());
julia_x_slider = new JUI::Slider(juliaset_dialog->Content());
julia_x_label = new JUI::Text(julia_x_slider);
julia_x_label->AlignCenterHorizontally();
julia_x_label->AlignTop();
julia_x_label->SetTextColor(Colors::Black);
julia_x_label->SetContent("X: 0");
julia_x_slider->Size({900_px, 25_px});
julia_x_slider->Interval(1e-5f); julia_x_slider->Minimum(0); julia_x_slider->Maximum(1);
julia_x_slider->ValueChanged += [this] (double value) {
julia_x_label->SetContent(std::format("X: {}", Math::FloorInt(value*360)));
value = value * 2;
value = value - 1;
u_julia_set.x = value;
};
auto* julia_y_slider = new JUI::Slider(juliaset_dialog->Content());
julia_y_slider = new JUI::Slider(juliaset_dialog->Content());
julia_y_label = new JUI::Text(julia_y_slider);
julia_y_label->AlignCenterHorizontally();
julia_y_label->AlignTop();
julia_y_label->SetTextColor(Colors::Black);
julia_y_label->SetContent("Y: 0");
julia_y_slider->Size({900_px, 25_px});
julia_y_slider->Position({0_px, 30_px});
julia_y_slider->Interval(1e-5f); julia_y_slider->Minimum(0); julia_y_slider->Maximum(1);
julia_y_slider->ValueChanged += [this] (double value) {
julia_y_label->SetContent(std::format("Y: {}", Math::FloorInt(value*360)));
value = value * 2;
value = value - 1;
u_julia_set.y = value;
@@ -523,6 +556,9 @@ void FractalInspectorApp::Update(float elapsed) {
Math::Round(u_translation.x, 4), Math::Round(u_translation.y, 4), readable_scale, fps);
fps_label->SetContent(fps_text);
}
float FractalInspectorApp::ReadableScale() {
@@ -556,6 +592,16 @@ void FractalInspectorApp::UpdateShaderUniforms(float elapsed) {
shader.SetVector2("u_translation", u_translation);
}
Vector2 solve(Vector2 a, Vector2 b) {
float real = (a.x*a.x) + (-1 * a.y*a.y);
float imag = (a.x*a.y)*2;
real += b.x;
imag += b.y;
return {real, imag};
}
void FractalInspectorApp::Draw() {
Shader::UseDefault();
@@ -570,6 +616,47 @@ void FractalInspectorApp::Draw() {
J2D::DrawRenderTarget(canvas, {0, 0});
J2D::End();
// This is annoying, leaving note here to comment it out when I work on this - maxine
J2D::Begin();
const float N = 512.f;
const float B = 2.f;
auto mpos_ipair = GetMouseCoordinates();
Vector2 mpos (mpos_ipair.x, mpos_ipair.y);
Vector2 R(GetWidth(), GetHeight());
Vector2 trans = Vector2(0, R.y) - u_translation;
Vector2 z = Vector2(0, 0);
Vector2 c = ScreenSpaceToFractalSpace(mpos);
Vector2 last_z = c;
J2D::FillCircle(Colors::Red, FractalSpaceToScreenSpace(ScreenSpaceToFractalSpace(mpos)), 6);
for (float i = 0.f; i < N; i++) {
float x = z.x;
float y = z.y;
Vector2 z_nplus1 = Vector2(x*x - y*y, y*x + x*y) + c;
J2D::DrawLine(Colors::White, FractalSpaceToScreenSpace(z), FractalSpaceToScreenSpace(last_z), 0.25);
last_z = z;
z = z_nplus1;
if (Vector2::Dot(z, z) > B*B) break;
}
//
J2D::End();
scene->Draw();
JGL::J2D::Begin(canvas, true);