Compare commits
6 Commits
Prerelease
...
main
Author | SHA1 | Date | |
---|---|---|---|
f0b097b782 | |||
e5fb5400c5 | |||
f316a3241d | |||
f64734c632 | |||
a9ca448a10 | |||
1ccfaeb85f |
@@ -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)
|
||||
|
||||
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
4
app.rc
Normal file
@@ -0,0 +1,4 @@
|
||||
MAINICON ICON "icon.ico"
|
||||
IDI_ICON1 ICON DISCARDABLE "icon.ico"
|
||||
MANIFEST ICON "icon.ico"
|
||||
AAA ICON "icon.ico"
|
@@ -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:
|
||||
};
|
||||
|
3
main.cpp
3
main.cpp
@@ -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.
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user