Filter "Rendering / Spline Spirograph"

Tuesday night, I was a bit stressed and tired from my day, and I looked for a way to relax. So, doing some code in G’MIC :slight_smile:

My tortuous mind wondered what it would be like to rotate a polygon and at the same time have it move along a random spline-like trajectory. Yes, it sounds like a silly idea, but I had a feeling it might turn out something cool.

I have to say that the first results obtained were a little beyond my expectations, so I decided to dig a little deeper and it’s with great pleasure that I can present to you today a new filter in G’MIC-Qt, named Rendering / Spline Spirograph, which allows you to do just that:

The filter looks like this when called from the plug-in:

As always when I’m doing this kind of experiment, I was amazed by the fact that the code didn’t take that long to write (prototyping with G’MIC is so cool :sunglasses:). And that’s going to benefit potentially a lot of people right away. Time well spent :slight_smile:

Here is the full source code for this new filter (56 lines of code, don’t tell me it’s too long! ).

Code for "Spline Spirograph" filter
#@gui Spline Spirograph : fx_spline_spirograph, fx_spline_spirograph
#@gui : Seed = int(0,0,65535)
#@gui : Randomize Seed = button()
#@gui : sep = separator()
#@gui : Complexity (%) = float(50,0,100)
#@gui : Sampling (%) = float(100,0,100)
#@gui : Radius (%) = float(20,0,100)
#@gui : Vertices = int(3,2,16)
#@gui : Twist = float(20,0,150)
#@gui : Offset (deg.) = float(0,-180,180)
#@gui : sep = separator()
#@gui : Colors = choice(3,"Default","HSV","Lines","Hot","Cool","Jet","Flag","Cube","Rainbow","Parula","Spring",\
# "Summer","Autumn","Winter","Bone","Copper","Pink","VGA","Algae","Amp","Balance","Curl","Deep","Delta","Dense","Diff",\
# "Gray","Haline","Ice","Matter","Oxy","Phase","Rain","Solar","Speed","Tarn","Tempo","Thermal","Topo","Turbid",\
# "Aurora","Hocuspocus","SRB2","Uzebox","Amiga7800","Amiga7800mess","Fornaxvoid1")
#@gui : Alpha Channel = bool(0)
#@gui : sep = separator()
#@gui : Normalization Strength (%) = float(50,0,100)
#@gui : Normalization Radius (%) = float(50,0,100)
#@gui : sep = separator()
#@gui : note = note("<small>Author: <i>David Tschumperlé</i>.      Latest Update: <i>2024/04/10</i>.</small>")
fx_spline_spirograph :
  seed,randomize_seed,complexity,sampling,radius,vertices,twist,\
    offset,colors,is_alpha,normalization_strength,normalization_radius=${1-12}
  if $randomize_seed seed:=v(65535) fi
  foreach {
    nm={n}
    if $is_alpha to_a else remove_opacity fi
    f 0 => canvas
    palette $colors r. 360,1,1,3,3 to_colormode. {0,s} => palette

    # Parameterization of a random spline curve.
    rs[canvas] 100,100,-1,2 ${}
    srand $seed noise_poissondisk. {max(5,lerp(100,0,$complexity%^0.3))}
    0 eval.. "i?da_push([u,x*w#$canvas%,y*h#$canvas%])" da_freeze. rm..
    sort. +,y channels. 1,2
    r. 1,{max(1,h*max(w#0,h#0)*($sampling%)^2)},1,2,5 => coords

    # Draw spirograph along spline.
    eval[coords] ":
      const R = $radius%*max(w#$canvas,h#$canvas);
      const N = $vertices;
      C = round(I);
      pP = [ 0,0 ];
      repeat (N + (N>2),k,
        ang = ($offset + lerp(0,360,k/N) + y*360*$twist/h)%360;
        P = round(C + R*cexp([0,ang°]));
        k>0?polygon(#$canvas,2,pP,P,-1,I(#$palette,ang,0,0,1));
        pP = P;
      )"
    k[canvas]
    n 0,255 normalize_local {10*$normalization_strength%},{max(1,($normalization_radius%)^3*10*max(w,h)%)}
  }
  u \{$seed\}\{0\}\{$density\}\{$radius\}\{$vertices\}\{$twist\}\{$offset\}\{$colors\}\
    \{$normalization_strength\}\{$normalization_radius\}

That’s all I had to say.
Feel free to play with it and post your own exciting results!

Cheers.

10 Likes

1 Like

:sunglasses:
I’d say it’s a surly idea!

1st tries, got nicely textured looks:

Wanted to animate the offset alone but forgot how to output to video :stuck_out_tongue:

This:

foo :
  800,800,1,3

  repeat 90 {
    f 0 fx_spline_spirograph 0,0,50,100,20,3,37.4,{4*$>},3,0,50,50
    w.
    on. frame.jpg,$>
  }

anim-ezgif.com-optimize

4 Likes

Thanks, something like this:
anim

4 Likes

I’ve added a Randomize Parameters button:

4 Likes

Got some pretty nice stuff with the randomizer:
image
image
image

Also got some weird ones:
image
got sampling at 2.53% here :rofl:
Also got a black image with sampling @ 0.48%.

3 Likes

Interesting!
Here’s a 2 vertices spline spirograph and it’s 3 vertices version (nothing else changed) :

Oh, and some bubbles :

Looks like a whole world of possibilities to explore :slight_smile:

3 Likes

Thank you @David_Tschumperle , that’s a great filter :+1: (I’m lovin’ those 2 random buttons :shushing_face: :grin:)

I tried your code (for animation) not being a programmer, is it possible to know what am I’m doing wrong? (I did even renamed the layer as “frame.jpg” but I’m a noob)

Screenshot of an error I get :

Hi,

I think you need to remove the command definition foo: .

Or if you want to keep it as is, you can copy the script in a foo.gmic file and call it with gmic in a command line:

gmic foo.gmic foo

Btw, this will save the frames to disk, you will need to open them “as layers” in gimp to save a gif.

If you don’t want to save the frames, you can comment this line ( add a # in front of it):
# on. frame.jpg,$>
You will still see the animation, thanks to w., shortcut to window[-1], which means “display last image in the list and go on”.
( Couldn’t think of a better explanation for window :slight_smile: )

I’m on Ubuntu 20.04, it is not working, never mind, that’s OK :wink:
Thank you @prawnsushi for your detailed explanations, I was not aware about image saved on the drive :+1:
Please have an absolute fantastic day.

I’m sorry, i answered from my phone alst time, so i didn’t check the result.

David added a randomizer button to the filter after giving the animation example.
So the spiro call is now wrong, there is an extra parameter before the last 2 ( …0,,50,50 ), but you still need to remove foo : to make it work in the custom code. Try this one instead :

# foo :

  800,800,1,3

  repeat 90 {
    f 0 
    fx_spline_spirograph 0,0,50,100,20,3,37.4,{4*$>},3,0,0,50,50
    w.
   #  on. frame.jpg,$>
  }

I commented the lines i mentioned earlier and it works for me in gmic_qt.

Try to replace some numbers by $> or $< to animate different things.

1 Like

To make things easier, I’ve added a new option to generate multiple animation frames in filter Rendering / Spline Spirograph :

Filters have been updated, so as always, press the “Update Filters” button to get the update.

Here is a video showing how it works:

4 Likes

That’s cool :slight_smile:
Maybe you should add parameters to choose what is animated? Checkboxes maybe?
I found animating sampling,radius, or vertices rahter fun actually!

1 Like

The offset parameter is clearly the obvious parameter to animate, for rendering a looping animation. I certainly don’t want to add a complex set of parameters for animating the other parameters (considering it’s possible to do this with a few lines of G’MIC script).

anim1-ezgif.com-optimize

1 Like

I was just putting myself in the shoes of a non-programmer (ok i’m not really one either) :wink:

Didn’t animate offset here :
nooffset

animated only offset here (and took a wrong frame too lol. getting subliminal):
pipes

2 Likes

Wowww, guys you’re going to fast for me :wink:

Thank you so much @prawnsushi for your answer and @David_Tschumperle to put it alive in G’MIC

I can see this as a background on a video to replace a green/blue BG screen :+1: for example exported as animated WebP

Please have an absolute fantastic day, and again thank you so much.

(webp example (1.4 mb, give it time to download) , just using the 2 buttons “Random”)

3 Likes

You’re welcome.
And you can keep David’s little foo command to animate other filters too. Just replace the "spirograph… " line by the code you get when you use the “copy filter button”, and use $> (increment) or $< ( decrement) to change parameters for each iteration of the loop.
Easy animation!

1 Like

Very nice tip,
thank you very much :+1:

1 Like

These results look awesome, David. Sorry for your stress, but happy it led to something real cool. :slight_smile: