DinkydauSet / ExploreFractals

A tool for testing the effect of Mandelbrot set Julia morphings
GNU General Public License v3.0
5 stars 1 forks source link

Animated zoom, rotation and adding and removing of Julia morphings #33

Open DinkydauSet opened 2 years ago

DinkydauSet commented 2 years ago

I would like this default behavior, especially when adding or removing a julia morphing: show a little animation of how the plane changes.

A challenge is to make this animation fast enough. It's not fast enough to re-render the whole fractal for every frame. That's what the program does when rendering animations with commandline options.

The reason for this feature is to make the program more intuitive. When I let family members use the program they complain that they don't understand what's happening. That's because they only see the end result of some action. In my head I think of rotations, morphings etc. as gradual actions so I want to show that intuition. I think it makes sense to have that intuition because real life material objects can't change form in 0 time units either. Change of form as something that happens gradually makes more sense.

DinkydauSet commented 2 years ago

This library has a generic transformation function for images: http://dlib.net/dlib/image_transforms/interpolation_abstract.h.html#transform_image It takes a transformation function and applies it. Rotation and scaling are already available, so if I implement the Julia transformation that could work.

Another library that has a mapping/transformation function: https://github.com/Dawoodoz/DFPSR/blob/master/Doc/ImageProcessing.html but I'm not sure if it has implementations of rotation and scaling.

DinkydauSet commented 2 years ago

Because I will probably implement some transformations anyway I decided to test if and how much faster bitblt is than an implementation by me (that may contain bugs but seems to work). Normally this happens in the GUI to show the fractal on the screen:

timerstart
graph.bitblt(draw_area, g, nana::point(offsetX, offsetY));
timerend("bitblt time")

I have added a timer to measure the time. It takes 0,0037 seconds at a resolution of 3030×1841.

My implementation of what bitblt does with a timer as well:

ARGB* src = graphics_pixelarray(g);
ARGB* dest = graphics_pixelarray(graph);
int src_x_from = offsetX;
int src_x_to = offsetX + viewport_size.width;
int src_y_from = offsetY;
int src_y_to = offsetY + viewport_size.height;
int dest_x_from = 0;
int dest_x_to = viewport_size.width;
int dest_y_from = 0;
int dest_y_to = viewport_size.height;

timerstart
int src_area_width = width - offsetX;
if (src_area_width > viewport_size.width) {
    src_area_width = viewport_size.width;
}
int dest_area_width = src_area_width;

ptrdiff_t src_skip_x = width - src_area_width;
ptrdiff_t dest_skip_x = viewport_size.width - dest_area_width;

ptrdiff_t src_idx = src_x_from + width * src_y_from;
ptrdiff_t dest_idx = dest_x_from + viewport_size.width * dest_y_from;

for (int src_y = src_y_from; src_y < src_y_to; src_y++)
{
    for (int src_x = src_x_from; src_x < src_x_to; src_x++)
    {
        dest[dest_idx++] = src[src_idx++];
    }
    src_idx += src_skip_x;
    dest_idx += dest_skip_x;
}

timerend("bitblt time")

It also takes 0,0037 seconds sometimes but the highs are higher. It appears bitblt is a little faster, especially for low resolutions.