From 206e037b40a05164e3a76a98258f38e5883a9124 Mon Sep 17 00:00:00 2001 From: ZERICO2005 <71151164+ZERICO2005@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:00:54 -0600 Subject: [PATCH] v1.0.9 | 2024/03/31 22:59 | Added a Julia Cordinate Point feature. Started work on making a better frame timer/pacer --- src/Common_Def.h | 17 +++-- src/Program_Def.h | 5 +- src/display_GUI.cpp | 45 +++++++++++--- src/fracCL.cpp | 12 ---- src/fractal.cpp | 8 +-- src/fractal.h | 10 +-- src/framePacer.cpp | 116 +++++++++++++++++++++++++++++++++++ src/framePacer.hpp | 63 +++++++++++++++++++ src/render.cpp | 81 ++++++++++++++++++------ src/temp_global_render.cpp | 2 +- src/temp_global_render.h | 2 +- src/user_data.cpp | 23 ++++++- src/user_data.h | 3 + text/Docs-(fracExpConfig).md | 2 +- 14 files changed, 325 insertions(+), 64 deletions(-) create mode 100644 src/framePacer.cpp create mode 100644 src/framePacer.hpp diff --git a/src/Common_Def.h b/src/Common_Def.h index b70e2ee..9223f6b 100644 --- a/src/Common_Def.h +++ b/src/Common_Def.h @@ -86,9 +86,9 @@ typedef int32_t dim32_t; // Right Circular Shift #define ROR(n,b) (((n) >> (b)) | ((n) << ((sizeof(n) * CHAR_BIT) - (b)))) - inline const char* bool_Text(const bool& b) { return b ? "true" : "false"; } - inline const char* Bool_Text(const bool& b) { return b ? "True" : "False"; } - inline const char* BOOL_Text(const bool& b) { return b ? "TRUE" : "FALSE"; } + constexpr inline const char* bool_Text(const bool& b) { return b ? "true" : "false"; } + constexpr inline const char* Bool_Text(const bool& b) { return b ? "True" : "False"; } + constexpr inline const char* BOOL_Text(const bool& b) { return b ? "TRUE" : "FALSE"; } // Replace with valueClamp(value) @@ -159,13 +159,10 @@ typedef int32_t dim32_t; // Returns the time in seconds fp64 getDecimalTime(); - inline nano64_t SECONDS_TO_NANO(fp64 t) { return (nano64_t)((t) * 1.0e9); } - inline fp64 NANO_TO_SECONDS(nano64_t t) { return ((fp64)(t) / 1.0e9); } - - // // Callocs the date and time in UTC - // const char* getDateAndTimeUTC( - // char DateDelimiter = '-', char DateSeparator = '_', char TimeDelimiter = '-' - // ); + constexpr inline nano64_t SECONDS_TO_NANO(fp64 s) { return (nano64_t)(s * 1.0e9); } + constexpr inline fp64 NANO_TO_SECONDS(nano64_t t) { return (fp64)t / 1.0e9; } + constexpr inline nano64_t FRAMERATE_TO_NANO(fp64 f) { return (nano64_t)(1.0e9 / f); } + constexpr inline fp64 NANO_TO_FRAMERATE(nano64_t t) { return (1.0e9) / (fp64)t; } /* Print Functions */ #define printFlush(...) printf(__VA_ARGS__); fflush(stdout) diff --git a/src/Program_Def.h b/src/Program_Def.h index 8815426..8cbcdb2 100644 --- a/src/Program_Def.h +++ b/src/Program_Def.h @@ -23,8 +23,8 @@ #define PROGRAM_DATE "2024/03/31" /* YYYY/MM/DD */ #define PROGRAM_V_MAJOR 1 #define PROGRAM_V_MINOR 1 -#define PROGRAM_V_PATCH 8 -#define PROGRAM_V_TAG "Rev-6 Developer Alpha" +#define PROGRAM_V_PATCH 9 +#define PROGRAM_V_TAG "Alpha" #define PROGRAM_VERSION STR_N(PROGRAM_V_MAJOR) "." STR_N(PROGRAM_V_MINOR) "." STR_N(PROGRAM_V_PATCH) " " PROGRAM_V_TAG /* float80 and float128 */ @@ -46,6 +46,7 @@ inline fp128 acos(fp128 x) { return acosq(x); } inline fp128 atan(fp128 x) { return atanq(x); } inline fp128 atan2(fp128 y, fp128 x) { return atan2q(y,x); } + inline fp128 hypot(fp128 x, fp128 y) { return hypotq(x,y); } inline fp128 log(fp128 x) { return logq(x); } inline fp128 log1p(fp128 x) { return log1pq(x); } inline fp128 log2(fp128 x) { return log2q(x); } diff --git a/src/display_GUI.cpp b/src/display_GUI.cpp index 89176d6..cbdab96 100644 --- a/src/display_GUI.cpp +++ b/src/display_GUI.cpp @@ -264,11 +264,17 @@ void horizontal_buttons_IMGUI(ImGuiWindowFlags window_flags) { #define FRAC frac.type.abs_mandelbrot uint32_t renderFP = (primaryRenderData.rendering_method == Rendering_Method::CPU_Rendering) ? primaryRenderData.CPU_Precision : primaryRenderData.GPU_Precision; const char* const renderMethod = (primaryRenderData.rendering_method == Rendering_Method::CPU_Rendering) ? "CPU" : "GPU"; + + static char powerText[64]; + if (FRAC.polarMandelbrot) { + snprintf(powerText,sizeof(powerText),"%6.4lf",FRAC.polarPower); + } + ImGui::Text( - "Formula: %llu Power: %6.4lf Super-Sample: %u Rendering: %s fp%u", - FRAC.formula,(FRAC.polarMandelbrot ? FRAC.polarPower : (fp64)FRAC.power),primaryRenderData.sample * primaryRenderData.sample,renderMethod,renderFP + "Formula: %llu Power: %s Super-Sample: %u Rendering: %s fp%u", + FRAC.formula,(FRAC.polarMandelbrot ? powerText : getPowerText(FRAC.power)),primaryRenderData.sample * primaryRenderData.sample,renderMethod,renderFP ); - #define temp_quad_len 64 + constexpr size_t temp_quad_len = 64; static char temp_quad_r[temp_quad_len]; static char temp_quad_i[temp_quad_len]; static char temp_quad_zr[temp_quad_len]; static char temp_quad_zi[temp_quad_len]; quadmath_snprintf(temp_quad_r,temp_quad_len,"%15.12Qf",FRAC.r); @@ -309,6 +315,7 @@ void Menu_Coordinates() { ImGui_BoundWindowPosition(config_data.GUI_Settings); if (frac.type_value == Fractal_ABS_Mandelbrot || frac.type_value == Fractal_Polar_Mandelbrot) { /* ABS and Polar */ + ImGui::SeparatorText("Cordinates"); #define FRAC frac.type.abs_mandelbrot #define NumberTextLen 64 @@ -341,17 +348,27 @@ void Menu_Coordinates() { Quad_InputText("i",FRAC.i,"%35.32Qf"); ImGui::Text("Zoom:"); Float_InputText("##zoom_input",FRAC.zoom,"%.5lf",strtod); + + ImGui::Text(" "); ImGui::Text("Julia Coordinate:"); static bool useJuliaSliders = true; if (useJuliaSliders == true) { float input_Zreal = (fp32)FRAC.zr; float input_Zimag = (fp32)FRAC.zi; if (ImGui::SliderFloat("zr",&input_Zreal,-2.0,2.0,"%.9f")) { FRAC.zr = (fp64)input_Zreal; } if (ImGui::SliderFloat("zi",&input_Zimag,-2.0,2.0,"%.9f")) { FRAC.zi = (fp64)input_Zimag; } + fp32 juliaAngle = (fp32)atan2(FRAC.zi, FRAC.zr); + if (ImGui::SliderAngle("Julia Angle",&juliaAngle,-360.0f,360.0f,"%.1f deg")) { + fp128 juliaMagnitude = hypot(FRAC.zr, FRAC.zi); + fp128 juliaTheta = (fp128)juliaAngle; + FRAC.zr = juliaMagnitude * cos(juliaTheta); + FRAC.zi = juliaMagnitude * sin(juliaTheta); + } } else { Quad_InputText("##input_Zreal",FRAC.zr,"%35.32Qf"); Quad_InputText("##input_zimag",FRAC.zi,"%35.32Qf"); } ImGui::Checkbox("Use Sliders", &useJuliaSliders); + ImGui::SeparatorText("Parameters"); ImGui::Text("Maximum Iterations:"); Int_InputText("##input_maxIter",FRAC.maxItr,"%u",strtoul,10); ImGui::Text("Fractal Formula:"); @@ -364,7 +381,7 @@ void Menu_Coordinates() { ImGui::Checkbox("Hexadecimal", &inputHexadecimal); /* Power */ if (frac.type_value == Fractal_ABS_Mandelbrot) { - ImGui::Text("Power: %s",getPowerText((int32_t)FRAC.power)); + ImGui::Text("Power: %s",getPowerText((uint32_t)FRAC.power)); Int_InputText("##input_power",FRAC.power,"%u",strtoul,10); } else if (frac.type_value == Fractal_Polar_Mandelbrot) { ImGui::Text("Power: %s",getPowerText(round(FRAC.polarPower))); @@ -421,7 +438,7 @@ void Menu_Fractal() { ImGui::Text("Fractal Radius: %.6lg",maxRadius); ImGui::Text("Cardioid Location: %.6lg",minRadius); if (Combo_FractalType == Fractal_ABS_Mandelbrot) { - ImGui::Text("Fractal Power: %s",getPowerText((int32_t)FRAC.power)); + ImGui::Text("Fractal Power: %s",getPowerText((uint32_t)FRAC.power)); int temp_input_power = (int)FRAC.power; ImGui::InputInt("##temp_input_power",&temp_input_power,1,1); FRAC.power = (uint32_t)temp_input_power; valueClamp(FRAC.power, 2, 6); // Support up to Sextic @@ -529,6 +546,8 @@ void Menu_Rendering() { (int32_t)Master.resY, ImGui_WINDOW_MARGIN * 2, 160, 320 ); + User_Rendering_Settings& Rendering_Settings = config_data.Rendering_Settings; + static const char* CPU_RenderingModes[] = {"fp32 | 10^5.7","fp64 | 10^14.4 (Default)","fp80 | 10^17.7","fp128 | 10^32.5"}; #ifndef BUILD_RELEASE static const char* GPU_RenderingModes[] = {"fp16 | 10^1.8","fp32 | 10^5.7 (Default)","fp64 | 10^14.4"}; @@ -621,7 +640,7 @@ void Menu_Rendering() { } #endif - ImGui::Separator(); + ImGui::SeparatorText("Super Screenshot Settings"); ImGui::Text("Sub Sample: %d", input_subSample * input_subSample); if (ImGui::SliderInt("##input_subSample",&input_subSample,1,24,"")) { @@ -646,8 +665,20 @@ void Menu_Rendering() { // ); // } // } + constexpr fp32 maxOutterRadius = 24.0f; + constexpr fp32 maxInnerRadius = maxOutterRadius - 1.0f; + ImGui::SeparatorText("Julia Cordinate Point"); + ImGui::Checkbox("Display Julia Point", &Rendering_Settings.JuliaPoint_Enabled); + ImGui::Text("Outer-Radius:"); + if (ImGui::SliderFloat("##OuterRadius",&Rendering_Settings.JuliaPoint_OuterRadius, 1.0f, maxOutterRadius, "%.2f")) { + valueClamp(Rendering_Settings.JuliaPoint_InnerRadius, 0.0f, Rendering_Settings.JuliaPoint_OuterRadius - 1.0f); + } + ImGui::Text("Inner-Radius"); + if (ImGui::SliderFloat("##InnerRadius",&Rendering_Settings.JuliaPoint_InnerRadius, 0.0f, maxInnerRadius, "%.2f")) { + valueClamp(Rendering_Settings.JuliaPoint_OuterRadius, Rendering_Settings.JuliaPoint_InnerRadius + 1.0f, maxOutterRadius); + } - ImGui::Separator(); + ImGui::SeparatorText("Frame Interpolation"); static const char* OpenCV_interpolation_mode_list[] = {"Nearest Neighbor (Default)","Linear","Cubic","Area","Lanczos"}; int_enum& OpenCV_interpolation_mode = config_data.Rendering_Settings.Frame_Interpolation_Method; ImGui::Text("Frame Interpolation Method:"); diff --git a/src/fracCL.cpp b/src/fracCL.cpp index 6049a1d..04ba6e1 100644 --- a/src/fracCL.cpp +++ b/src/fracCL.cpp @@ -53,27 +53,15 @@ void calculate_GPU_Hardware_Hash(uint64_t& hash) { fnv1a_hash_continous(hash,(uint8_t*)(void*)& DeviceMaxComputeUnits,sizeof(DeviceMaxComputeUnits) ); - fnv1a_hash_continous(hash,(uint8_t*)(void*)& - DeviceMaxWorkGroupSize,sizeof(DeviceMaxWorkGroupSize) - ); fnv1a_hash_continous(hash,(uint8_t*)(void*)& DeviceGlobalMemSize,sizeof(DeviceGlobalMemSize) ); - fnv1a_hash_continous(hash,(uint8_t*)(void*)& - DeviceLocalMemSize,sizeof(DeviceLocalMemSize) - ); fnv1a_hash_continous(hash,(uint8_t*)(void*)& DeviceFP32Config,sizeof(DeviceFP32Config) ); fnv1a_hash_continous(hash,(uint8_t*)(void*)& DeviceFP64Config,sizeof(DeviceFP64Config) ); - fnv1a_hash_continous(hash,(uint8_t*)(void*)& - KernelWorkGroupSize,sizeof(KernelWorkGroupSize) - ); - fnv1a_hash_continous(hash,(uint8_t*)(void*)& - KernelLocalMemSize,sizeof(KernelLocalMemSize) - ); } int32_t init_OpenCL() { diff --git a/src/fractal.cpp b/src/fractal.cpp index 6dc8c6e..03f5385 100644 --- a/src/fractal.cpp +++ b/src/fractal.cpp @@ -12,14 +12,14 @@ #include "fractal.h" /* Safe Method of accessing PowerText */ -const char* getPowerText(int32_t p) { - if (p >= 0 && p <= (int32_t)ARRAY_LENGTH(PowerText)) { +const char* getPowerText(uint32_t p) { + if (p < (uint32_t)ARRAY_LENGTH(PowerText)) { return PowerText[p]; } return NULL; } const char* getPowerText(fp64 p) { - return getPowerText((int32_t)p); + return getPowerText((uint32_t)p); } uint64_t limitFormulaID(uint32_t power, uint64_t formula) { @@ -69,7 +69,7 @@ void setDefaultParameters(Fractal_Data* frac, enum FractalTypeEnum type) { FRAC.swapJuliaSplit = false; FRAC.cursorZValue = false; FRAC.showFloatingJulia = false; - FRAC.adjustZoomToPower = true; + FRAC.adjustZoomToPower = false; FRAC.polarMandelbrot = false; FRAC.lockToCardioid = false; FRAC.flipCardioidSide = false; diff --git a/src/fractal.h b/src/fractal.h index f7fb93a..a2bc6ad 100644 --- a/src/fractal.h +++ b/src/fractal.h @@ -29,10 +29,10 @@ enum FractalTypeEnum { const char* const PowerText[] = { "Constant", "Linear" , "Quadratic", "Cubic" , "Quartic" , "Quintic" , "Sextic" , "Septic" , "Octic" , "Nonic" , "Decic" , "Undecic" , "Dodecic" , "Tridecic" , "Tetradecic" , "Pentadecic", "Hexadecic", "Heptadecic", "Octadecic", "Nonadecic", - "Icosic" , "Unicosic", "Duocosic" , "Triacosic", "Tetraicosic", "Pentacosic", "Hexacosic", "Heptacosic", "Octacosic", "Nonacosic" + "Icosic" , "Unicosic", "Duocosic" , "Triacosic", "Tetraicosic", "Pentacosic", "Hexacosic", "Heptacosic", "Octacosic", "Nonacosic" }; /* Safe Method of accessing PowerText */ -const char* getPowerText(int32_t p); +const char* getPowerText(uint32_t p); const char* getPowerText(fp64 p); inline fp64 getABSFractalMinRadius(fp64 power) { @@ -150,8 +150,8 @@ void setDefaultParameters(Fractal_Data* frac, enum FractalTypeEnum type); template void coordinate_to_pixel(fpX xI, fpX yI, int32_t* xO, int32_t* yO, const ABS_Mandelbrot* param, const Render_Data* ren) { /* Reverses Transformations */ - fpX xC = xI * cos(-(fpX)param->rot) - yI * sin(-(fpX)param->rot); - fpX yC = yI * cos(-(fpX)param->rot) + xI * sin(-(fpX)param->rot); + fpX xC = xI * cos(-(fpX)param->rot) - yI * sin(-(fpX)param->rot) - param->r; + fpX yC = yI * cos(-(fpX)param->rot) + xI * sin(-(fpX)param->rot) - param->i; xC /= (fpX)param->sX; yC /= (fpX)param->sY; /* Normalizes Coordinates */ @@ -172,7 +172,7 @@ void coordinate_to_image_cordinate(fpX xI, fpX yI, fp32* xO, fp32* yO, const ABS /* Normalizes Coordinates */ dim32_t resX = ren->resX - 1; dim32_t resY = ren->resY - 1; - dim32_t resZ = (resX >= resY) ? resY : resX;\ + dim32_t resZ = (resX >= resY) ? resY : resX; *xO = (fp32)( (xC * pow((fpX)10.0, (fpX)param->zoom) / (fpX)2.0 * (((fpX)resZ))) + (((fpX)resX) / (fpX)2.0) ); *yO = (fp32)( (-yC * pow((fpX)10.0, (fpX)param->zoom) / (fpX)2.0 * (((fpX)resZ))) + (((fpX)resY) / (fpX)2.0) ); } diff --git a/src/framePacer.cpp b/src/framePacer.cpp new file mode 100644 index 0000000..74e6d8d --- /dev/null +++ b/src/framePacer.cpp @@ -0,0 +1,116 @@ +/* +** Author: zerico2005 (2023-2024) +** Project: ABS-Fractal-Explorer +** License: MIT License +** A copy of the MIT License should be included with +** this project. If not, see https://opensource.org/license/MIT +*/ + +#include "Common_Def.h" +#include "framePacer.hpp" + +/* class Frame_Pacer */ + /* public */ + /* Constructors */ + Frame_Pacer::Frame_Pacer() { + init_Frame_Pacer(0,0); + } + + Frame_Pacer::Frame_Pacer(nano64_t frameTime, nano64_t pollTime) { + init_Frame_Pacer(frameTime, pollTime); + } + + Frame_Pacer::Frame_Pacer(fp64 frameRate, fp64 pollRate) { + init_Frame_Pacer(FRAMERATE_TO_NANO(frameRate), FRAMERATE_TO_NANO(pollRate)); + } + + + /* Variables */ + nano64_t Frame_Pacer::get_FrameTime() const { + return FrameTime; + } + fp64 Frame_Pacer::get_FrameRate() const { + return NANO_TO_FRAMERATE(FrameTime); + } + + void Frame_Pacer::set_FrameTime(nano64_t frameTime) { + FrameTime = frameTime; + } + void Frame_Pacer::set_FrameRate(fp64 frameRate) { + set_FrameTime(FRAMERATE_TO_NANO(frameRate)); + } + + /* Functions */ + // Force starts the next frame + void Frame_Pacer::forceNewFrame() { + nano64_t currentTime = getNanoTime(); + Frame_Start = currentTime; + Next_Frame = Frame_Start + FrameTime; + + nano64_t frameTime = Frame_Start - currentTime; + update_Maximum_FrameTime(frameTime); + } + // Checks if the next frame is ready + bool Frame_Pacer::checkNewFrame() const { + return (timeUntilNextFrame() <= 0) ? true : false; + } + // Checks and starts the next frame + bool Frame_Pacer::startNewFrame() { + if (checkNewFrame() == true) { + forceNewFrame(); + return true; + } + return false; + } + + nano64_t Frame_Pacer::timeUntilNextFrame() const { + return Next_Frame - getNanoTime(); + } + fp64 Frame_Pacer::secondsUntilNextFrame() const { + return NANO_TO_SECONDS(timeUntilNextFrame()); + } + + // Will yeild/sleep until the next frame + void Frame_Pacer::waitForNextFrame(nano64_t threshold) { + if (checkNewFrame() == true) { return; } + while (timeUntilNextFrame() > threshold) { + std::this_thread::yield(); + } + while (checkNewFrame() == false) { /* Spin-Lock */ } + forceNewFrame(); + } + void Frame_Pacer::waitForNextFrame(fp64 threshold) { + waitForNextFrame(SECONDS_TO_NANO(threshold)); + } + + /* Statistics */ + nano64_t Frame_Pacer::get_MaximumFrameTime() const { + return Display_Maximum_FrameTime; + } + fp64 Frame_Pacer::get_MaximumFrameRate() const { + return NANO_TO_FRAMERATE(Display_Maximum_FrameTime); + } + + /* private */ + void Frame_Pacer::init_Frame_Pacer(nano64_t frameTime, nano64_t pollTime) { + FrameTime = frameTime; + PollTime = pollTime; + + Frame_Start = getNanoTime(); + Next_Frame = Frame_Start + frameTime; + Delta_Time = 0; + + Display_Maximum_FrameTime = 0; + Maximum_FrameTime = 0; + Maximum_Timer = getNanoTime(); + } + void Frame_Pacer::update_Maximum_FrameTime(nano64_t frameTime) { + if (frameTime > Maximum_FrameTime) { + Maximum_FrameTime = frameTime; + } + if (getNanoTime() - Maximum_Timer > PollTime) { + Maximum_Timer = getNanoTime(); + Display_Maximum_FrameTime = Maximum_FrameTime; + Maximum_FrameTime = 0; + } + } \ No newline at end of file diff --git a/src/framePacer.hpp b/src/framePacer.hpp new file mode 100644 index 0000000..0b23166 --- /dev/null +++ b/src/framePacer.hpp @@ -0,0 +1,63 @@ +/* +** Author: zerico2005 (2023-2024) +** Project: ABS-Fractal-Explorer +** License: MIT License +** A copy of the MIT License should be included with +** this project. If not, see https://opensource.org/license/MIT +*/ + +#ifndef FRAME_PACER_HPP +#define FRAME_PACER_HPP + +#include "Common_Def.h" + +class Frame_Pacer { + public: + /* Constructors */ + Frame_Pacer(); + Frame_Pacer(nano64_t frameTime, nano64_t pollTime = SECONDS_TO_NANO(1.0 / 6.0)); + Frame_Pacer(fp64 frameRate, fp64 pollRate = (1.0 / 6.0)); + + /* Variables */ + nano64_t get_FrameTime() const; + fp64 get_FrameRate() const; + + void set_FrameTime(nano64_t frameTime); + void set_FrameRate(fp64 frameRate); + + /* Functions */ + // Force starts the next frame + void forceNewFrame(); + // Checks if the next frame is ready + bool checkNewFrame() const; + // Checks and starts the next frame + bool startNewFrame(); + + nano64_t timeUntilNextFrame() const; + fp64 secondsUntilNextFrame() const; + // Will yeild/sleep until the next frame + void waitForNextFrame(nano64_t threshold = SECONDS_TO_NANO(1.0 * 1.0e-3)); + // Will yeild/sleep until the next frame + void waitForNextFrame(fp64 threshold = (1.0 * 1.0e-3)); + + + /* Statistics */ + nano64_t get_MaximumFrameTime() const; + fp64 get_MaximumFrameRate() const; + + private: + nano64_t FrameTime; + nano64_t PollTime; + + nano64_t Frame_Start; + nano64_t Next_Frame; + nano64_t Delta_Time; + + nano64_t Display_Maximum_FrameTime; + nano64_t Maximum_FrameTime; + nano64_t Maximum_Timer; + void init_Frame_Pacer(nano64_t frameTime, nano64_t pollTime); + void update_Maximum_FrameTime(nano64_t frameTime); +}; + +#endif /* FRAME_PACER_HPP */ \ No newline at end of file diff --git a/src/render.cpp b/src/render.cpp index 5b4949e..11d623f 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -353,7 +353,7 @@ bool windowResizingCode(dim32_t* resX = nullptr, dim32_t* resY = nullptr) { } void set_Window_Fullscreen_Mode(Display_Fullscreen::Display_Fullscreen_Enum fullscreen_mode) { - return; // This code creates werid problems + //return; // This code creates werid problems switch (fullscreen_mode) { // case Display_Fullscreen::Fullscreen: // SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); @@ -368,12 +368,13 @@ void set_Window_Fullscreen_Mode(Display_Fullscreen::Display_Fullscreen_Enum full case Display_Fullscreen::Windowed: default: { - //SDL_SetWindowFullscreen(window, 0); + SDL_SetWindowFullscreen(window, 0); int32_t dispResX, dispResY, initResX, initResY, initPosX, initPosY; const DisplayInfo* disp = getDisplayFromWindowPosition(window); if (disp != nullptr) { disp->getResolution(dispResX, dispResY); disp->getResolution(initResX, initResY); + disp->getPosition(initPosX,initPosY); calculate_init_window_size(dispResX, dispResY, initResX, initResY, initPosX, initPosY); force_resizeWindow(initResX, initResY); SDL_SetWindowPosition(window, initPosX, initPosY); @@ -483,14 +484,10 @@ void initFunctionTimers() { // #define stretchValue(s) pow(2.0,-abs(s)) // #define zoomDefault(p) (-log10(getABSFractalMaxRadius((fp64)(p))) - 0.01) -void moveCord(fp128* x, fp128* y, fp64 angle, fp64 speed) { - *x += speed * cos(angle); - *y += speed * sin(angle); -} - -void moveCord(fp64* x, fp64* y, fp64 angle, fp64 speed) { - *x += speed * cos(angle); - *y += speed * sin(angle); +template +void moveCord(fpX* x, fpX* y, fp64 angle, fp64 speed) { + *x += (fpX)speed * cos((fpX)angle); + *y += (fpX)speed * sin((fpX)angle); } bool funcTimeDelay(Key_Function::Key_Function_Enum func) { @@ -997,7 +994,7 @@ int start_Render(std::atomic& QUIT_FLAG, std::atomic& ABORT_RENDERIN updateFrameRate(FRAME_RATE + FRAME_RATE_OFFSET); GUI_FrameTimer = TimerBox(GUI_FrameTime); - TimerBox maxFrameReset = TimerBox(1.0/5.0); /* Keeps track of longest frame times */ + TimerBox maxFrameReset = TimerBox(1.0 / 5.0); /* Keeps track of longest frame times */ write_Update_Level(Change_Level::Full_Reset); while (QUIT_FLAG == false) { { // Accesses ABORT_RENDERING only when Abort_Rendering_Flag changes to reduce unnecessary accesses @@ -1216,8 +1213,8 @@ void calculate_init_window_size( dim32_t& initResX, dim32_t& initResY, dim32_t& initPosX, dim32_t& initPosY ) { - initPosX = 0; - initPosY = 0; + // initPosX = 0; + // initPosY = 0; initResX -= RESX_Margin; initResY -= RESY_Margin; if (config_data.Display_Preferences.ScaleWindowToScreenSize == true) { @@ -1261,8 +1258,12 @@ int init_Render(std::atomic& QUIT_FLAG, std::atomic& ABORT_RENDERING } dispResX = initResX; dispResY = initResY; - //printFlush("\nOld: %dx%d %d,%d",initResX,initResY,initPosX,initPosY); + calculate_init_window_size( + dispResX, dispResY, + initResX, initResY, + initPosX, initPosY + ); switch (config_data.Display_Preferences.Bootup_Fullscreen) { case Display_Fullscreen::Windowed_Fullscreen: break; @@ -1275,6 +1276,7 @@ int init_Render(std::atomic& QUIT_FLAG, std::atomic& ABORT_RENDERING ); } + //printFlush("\nNew: %dx%d %d,%d",initResX,initResY,initPosX,initPosY); { #ifndef MANUAL_FRAME_RATE_OVERRIDE @@ -1379,12 +1381,12 @@ int terminate_Render() { terminateKeyboardGraphics(); clear_KeyBind_PresetList(); ImGui_ImplSDLRenderer2_Shutdown(); - ImGui_ImplSDL2_Shutdown(); - ImGui::DestroyContext(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); + SDL_DestroyWindow(window); + SDL_Quit(); FREE(TestGraphic.vram); return 0; } @@ -1597,6 +1599,45 @@ int displayFracImage(ImageBuffer* image, Render_Data* ren) { return 0; } +void renderJuliaCordinatePoint(const BufferBox& box, const Render_Data* ren) { + const User_Rendering_Settings& Rendering_Settings = config_data.Rendering_Settings; + if (Rendering_Settings.JuliaPoint_Enabled == false) { return; } + if (frac.type.abs_mandelbrot.zr == 0.0 && frac.type.abs_mandelbrot.zi == 0.0) { return; } + if (ren == nullptr) { + printError("Unable to renderJuliaCordinatePoint(), Render_Data is nullptr"); + return; + } + if (validateBufferBox(&box,true) == false) { + printError("Unable to renderJuliaCordinatePoint(), to invalid BufferBox"); + return; + } + const int32_t outsideRadiusSquared = + (int32_t)(Rendering_Settings.JuliaPoint_OuterRadius * Rendering_Settings.JuliaPoint_OuterRadius); + const int32_t insideRadiusSquared = + (int32_t)(Rendering_Settings.JuliaPoint_InnerRadius * Rendering_Settings.JuliaPoint_InnerRadius); + int32_t pointRadius = (int32_t)ceil(Rendering_Settings.JuliaPoint_OuterRadius); + int32_t posX, posY; + coordinate_to_pixel( + frac.type.abs_mandelbrot.zr, frac.type.abs_mandelbrot.zi, + &posX, &posY, &frac.type.abs_mandelbrot, ren + ); + for (int32_t y = posY - pointRadius; y <= posY + pointRadius; y++) { + if (y < 0 || y >= box.resY) { continue; } + for (int32_t x = posX - pointRadius; x <= posX + pointRadius; x++) { + if (x < 0 || x >= box.resX) { continue; } + int32_t squaredDistance = (posX - x) * (posX - x) + (posY - y) * (posY - y); + if ( + (squaredDistance >= outsideRadiusSquared) || + (squaredDistance < insideRadiusSquared) + ) { continue; } + size_t offset = ((size_t)x * box.channels) + (getBufferBoxPitch(&box) * (size_t)y); + for (size_t i = 0; i < box.channels; i++) { + box.vram[offset + i] = (uint8_t)(((uint32_t)box.vram[offset + i] + (uint32_t)0xFF) / 2); + } + } + } +} + int transformFracImage(ImageBuffer* image, Render_Data* ren) { if (image == nullptr) { printError("ImageBuffer* image is NULL"); return -1; } if (image->vram == nullptr) { printError("ImageBuffer* image->vram is NULL"); return -1; } @@ -1674,10 +1715,10 @@ int transformFracImage(ImageBuffer* image, Render_Data* ren) { // } //printfInterval(0.6,"\n%p: %ux%u %uC %uP",blit.vram,blit.resX,blit.resY,blit.channels,blit.padding); - + renderJuliaCordinatePoint(blit, ren); // nano64_t startTime0 = getNanoTime(); - copyBuffer_VeritcalOffset(temp_MASTER,blit,(size_t)RESY_UI); + copyBuffer_VeritcalOffset(temp_MASTER, blit, (size_t)RESY_UI); // uint8_t* dstBuf = temp_MASTER.vram; // Buffer_Data srcData; set_Buffer_Data(srcData, // blit.resX, blit.resY, diff --git a/src/temp_global_render.cpp b/src/temp_global_render.cpp index c9e96c1..be3f7fc 100644 --- a/src/temp_global_render.cpp +++ b/src/temp_global_render.cpp @@ -73,7 +73,7 @@ SDL_Texture* kTexture = nullptr; // Keyboard graphic /* Rendering */ - + //#define Use_OpenCV_Scaler SDL_Texture* scale_tex = nullptr; diff --git a/src/temp_global_render.h b/src/temp_global_render.h index d1aeb50..d279c9e 100644 --- a/src/temp_global_render.h +++ b/src/temp_global_render.h @@ -73,7 +73,7 @@ extern SDL_Texture* kTexture; // Keyboard graphic /* Rendering */ - + #define Use_OpenCV_Scaler extern SDL_Texture* scale_tex; diff --git a/src/user_data.cpp b/src/user_data.cpp index f1ecccc..4aecd62 100644 --- a/src/user_data.cpp +++ b/src/user_data.cpp @@ -60,7 +60,10 @@ constexpr User_Configuration_Data Default_Config = { }, .Rendering_Settings = { .Hardware_Hash = 0x0, - .Frame_Interpolation_Method = OPENCV_Interpolation::OPENCV_INTER_NEAREST + .Frame_Interpolation_Method = OPENCV_Interpolation::OPENCV_INTER_NEAREST, + .JuliaPoint_Enabled = true, + .JuliaPoint_OuterRadius = 8.0f, + .JuliaPoint_InnerRadius = 2.4f } }; @@ -117,6 +120,8 @@ constexpr User_Configuration_Data Default_Config = { void clean_Rendering_Settings(User_Rendering_Settings& config_data) { const User_Rendering_Settings& config_default = Default_Config.Rendering_Settings; clean_config_data(Frame_Interpolation_Method, 0, OPENCV_Interpolation::OPENCV_INTER_COUNT); + clean_config_data(JuliaPoint_OuterRadius, 1.0f, 24.0f); + clean_config_data(JuliaPoint_InnerRadius, 0.0f, config_data.JuliaPoint_OuterRadius - 1.0f); } void clean_User_Configuration_Data(User_Configuration_Data& config_data) { @@ -125,6 +130,7 @@ constexpr User_Configuration_Data Default_Config = { clean_Display_Preferences(config_data.Display_Preferences); clean_GUI_Settings(config_data.GUI_Settings); clean_Screenshot_Settings(config_data.Screenshot_Settings); + clean_Rendering_Settings(config_data.Rendering_Settings); } #undef clean_config_data @@ -385,6 +391,12 @@ void load_config_values(User_Configuration_Data& config_data, const char* Config textToUint64(get_config_value(Config_Text,config_label,"Hardware_Hash")); config_data.Rendering_Settings.Frame_Interpolation_Method = textToEnum(get_config_value(Config_Text,config_label,"Frame_Interpolation_Method")); + config_data.Rendering_Settings.JuliaPoint_Enabled = + textToBool_TrueDefault(get_config_value(Config_Text,config_label,"JuliaPoint_Enabled")); + config_data.Rendering_Settings.JuliaPoint_OuterRadius = + textToFloat32(get_config_value(Config_Text,config_label,"JuliaPoint_OuterRadius")); + config_data.Rendering_Settings.JuliaPoint_InnerRadius = + textToFloat32(get_config_value(Config_Text,config_label,"JuliaPoint_InnerRadius")); } int import_config_data(User_Configuration_Data& config_data, const char* path) { @@ -595,6 +607,15 @@ int export_config_data(User_Configuration_Data& config_data, const char* path) { fprintf(file,"\n\tFrame_Interpolation_Method: %d", config_data.Rendering_Settings.Frame_Interpolation_Method ); + fprintf(file,"\n\tJuliaPoint_Enabled: %s", + bool_Text(config_data.Rendering_Settings.JuliaPoint_Enabled) + ); + fprintf(file,"\n\tJuliaPoint_OuterRadius: %.6f", + config_data.Rendering_Settings.JuliaPoint_OuterRadius + ); + fprintf(file,"\n\tJuliaPoint_InnerRadius: %.6f", + config_data.Rendering_Settings.JuliaPoint_InnerRadius + ); fclose(file); return 0; diff --git a/src/user_data.h b/src/user_data.h index 92bf6e3..721c4c6 100644 --- a/src/user_data.h +++ b/src/user_data.h @@ -69,6 +69,9 @@ struct User_Rendering_Settings { uint64_t Hardware_Hash; int_enum Frame_Interpolation_Method; + bool JuliaPoint_Enabled; + fp32 JuliaPoint_OuterRadius; + fp32 JuliaPoint_InnerRadius; }; typedef struct User_Rendering_Settings User_Rendering_Settings; /* User Data Configuration */ diff --git a/text/Docs-(fracExpConfig).md b/text/Docs-(fracExpConfig).md index b23c62e..b3d2af6 100644 --- a/text/Docs-(fracExpConfig).md +++ b/text/Docs-(fracExpConfig).md @@ -36,7 +36,7 @@ Configures how the program should determine which display to open on. Doesn't have an effect if the system only has one monitor. 0. Automatic: Goes through a multi-step process to determine which display to use - * If the current and previous `Display_Config_Hash` values match, the display will open on the `Previous_Display_Used`. + * (Skipped due to some bugs/issues) If the current and previous `Display_Config_Hash` values match, the display will open on the `Previous_Display_Used`. * If the current and previous `Display_Config_Hash` do **not** match, or the `Previous_Display_Used` is not set, the display will open on the `Cursors Position`. * If the `Cursor Position` display is invalid, the `Primary Display` will be used. * If the `Primary Display` is also invalid, then the first valid display will be used.