Creative Coding with G'MIC

Today, I was in the mood for “social distancing” (it’s all the rage these days!), so I decided to try implementing a simple particle system in G’MIC.
The idea : putting a lot of particles in the same image, with the rules:

  • Particles should move away from each others, and from the image border.
  • plus added a repulsive particle that is moving fast.

And see what happened… I’ve found it quite nice, so I’m posting it here :slight_smile:

ccoding

A more higher-resolution video is available here :

For those interested, here is the G’MIC script that generates the frames:

foo :
  512,512,1,3
  1,300,1,2,u(w#-1-1)

  t=0
  do
    xrep,yrep={w#0*(0.5+0.3*[cos(4.2*$t),sin(2.7*$t)])}
    t+=0.01

    # Render particles.
    +f.. 0 eval.. ">ellipse(#-1,R,G,2,2,0,1,255)"
    circle. $xrep,$yrep,8,1,255,0,0
    *... 'd=y/h;[0.24+0.75*d,0.92,0.99-0.3*d]' max[0,-1]
    w..

    # Compute and apply particle velocity.
    +. '"*
      add_veloc(Q,strength,sigma) = (
        U = P - Q;
        nU = norm(U);
        U/=max(1e-5,nU);
        w = strength*gauss(nU,sigma,0);
        sumw+=w;
        V+=w*U;
      );

      P = I(#1);
      V = [ 0,0 ];
      sumw = 0;

      for (p = 0, p<h, ++p, p!=y?add_veloc(I[#1,p],5,10));
      add_veloc([0,P[1]],10,40);
      add_veloc([w#0-1,P[1]],10,40);
      add_veloc([P[0],0],10,40);
      add_veloc([P[0],h#0-1],10,40);
      add_veloc(["$xrep,$yrep"],50,50);
      2.8*V/sumw"'
    wait 30

  while {*}" && "!{*,ESC}
  rm w[] 0
10 Likes

Cool but also grossing me out a bit because a long time ago one of my evergreen bushes had an infestation of hundreds of worms or caterpillars (I don’t remember what they were) that would pandiculate whenever I walked by. I ended up spraying the entire plant but they only dried up. :sweat_smile:

:upside_down_face:

2 Likes

Thanks for giving me a less repulsive visual. :tropical_fish:

1 Like

My version is more natural :wink:

Show us the code! :wink:

Later, I need to improve colors a bit :roll_eyes: :wink:

@s7habo breaks quarantine and goes to the coral reefs to extract the DNA.

1 Like

I’ve made a small update. It’s now rendered in 3D.

ezgif.com-optimize

Source code:

repulsive_particles3d :
  512,512,1,3
  1,900,1,3,u(w#-1-1)
 
  t=0
  do
    xrep,yrep,zrep={w#0*(0.5+0.3*[cos(4.2*$t),sin(2.7*$t),cos(1.9*$t)])}
    t+=0.01
 
    # Render 3D particles.
    N=$!
    repeat h circle3d {"I[#1,"$>"]"},4 done
    +3d[$N--1] col3d. 255 o3d. 0.75
    circle3d $xrep,$yrep,$zrep,20 col3d. 255,0,0
    +3d[-2,-1]
    box3d 512,512,512 p3d. 1 o3d. 0.4 +3d[-2,-1]
    -3d. {0,[w,w,w]/2} r3d. 1,1,0,34 #r3d. 0,1,0,{80*$t}
    f3d 400
    +f[0] 0 j3d. ..,50%,50%,150,1,2
    *[0] 'd=y/h;[0.24+0.75*d,0.92,0.99-0.3*d]' max[0,-1]
    rm. w[0]
 
    # Compute and apply 3D particle velocity.
    +. '"*
     add_veloc(Q,strength,sigma) = (
       U = P - Q;
       nU = norm(U);
       U/=max(1e-5,nU);
       w = strength*gauss(nU,sigma,0);
       sumw+=w;
       V+=w*U;
     );
 
     P = I(#1);
     V = [ 0,0,0 ];
     sumw = 0;
 
     for (p = 0, p<h, ++p, p!=y?add_veloc(I[#1,p],5,20));
     const W = w#0-1;
     add_veloc([0,P[1],P[2]],10,10);
     add_veloc([P[0],0,P[2]],10,10);
     add_veloc([P[0],P[1],0],10,10);
     add_veloc([W,P[1],P[2]],10,10);
     add_veloc([P[0],W,P[2]],10,10);
     add_veloc([P[0],P[1],W],10,10);
 
     add_veloc(["$xrep,$yrep,$zrep"],50,70);
     2.8*V/sumw"'
    wait 30
 
  while {*}" && "!{*,ESC}
  rm w[] 0
4 Likes

I like the 3d one more. Could easily become a lighting or fire effect or animation. :wink:

Tonight, I wanted to think about something else, I quickly coded a 50-lines G’MIC script, which mixes concepts of animation, 3D objects & images. I wonder if it wouldn’t be an interesting basis to explain creative-coding development in G’MIC, as a text or video tut.
The script covers many different things we can found in G’MIC, so it could be interesting.

Anyone interested?

ezgif.com-optimize (2)

4 Likes

Issue: the orange-green ball goes through the sheet 2-3 times.

Tutorial: I prefer text steps and video examples.

Suggestion: Add (or adjust) speed curve(s) to make it even more realistic.

It reminds me of a youtube video where a Blender user created a video showing off partying balls falling down the stair. That animation of yours is just as satisfying.

Even after all these years, I’m still amazed at how it’s possible to write creative short scripts in G’MIC, once you know how the language works.

My latest trial, done this afternoon in less than 15mn (17 lines!):

snow :
  shape_snowflake 300 repeat 100 { f:=3+0.5*$> +r[0] $f%,$f%,1,1,2 rotate. {lerp(0,90,$>/10)},1,0 } rm[0] a z,0.5 autocrop. r2dx. 16
  l[] { 8,1,1,{3*1000} rand. 0,1 s c,-3 rbf 1000,0,1 a c }
  repeat {w} {
    400,400
    {1,s/3},1,1,1,"
      begin(P = I[#1,"$>"]; S = vector(#w#0*h#0*3,255));
      k3 = 3*x;
      x = P[k3]*w#-1;
      y = P[k3 + 1]*h#-1;
      r = round(lerp(0,d#0 - 1,cut(P[k3 + 2],0,1)));
      M = crop(#0,0,0,r,w#0,h#0,1);
      draw(#-1,S,x,y,0,0,w#0,h#0,1,1,0.75,M);
    " rm.
    to. "Snow",0.5~,0.5~,${"font macondo,150"},3,1,255
    w. on. frame.png,$> rm.
  }

generates this nice animation:

snow-ezgif.com-optimize

Here again, RBF FTW! (special message to @grosgood :slight_smile: )

3 Likes

This morning, a colleague of mine talked about the fact that the Rock-Paper-Scissor game can be implemented with a cellular automata, and that it creates nice spiral-looking effects when applied on images (see for instance this page for explanations about this).

So I decided to do this with G’MIC, but of course it quickly drifted into amusing experiments:

  • Done for 3D volumetric images
  • Decorate the result with some water-like lighting.

Code;

Show/Hide
foo :
 
  # Generate volumetric image.
  150,150,150,1,v(2)
  repeat 100 {
    f "const boundary = 2;
       const threshold = 9;
       winner = (i + 1)%3;
       H = histogram(crop(x - 1,y - 1,z - 1,3,3,3),1,winner,winner);
       H[0]>=threshold?winner:i"
    w.
  }
 
  # Decorate with water-like effect.
  r 480,480,100%,1,6 b. xy,1%,2 c. 0,2 round. 1
  +==[0] 1 +==[0] 2 ==[0] 0 n 0,255
  foreach { i=$> s z
    col0=0,0,0
    col1=128,0,0
    col2=200,128,32
    foreach {
      channels. -3,0 100%,100%,1,3 fc. ${col$i}
      +fx_drop_water 1,20,2,80,0,3,35,10,1,0.5,0.25,0.5,0.75,0.05,0.15,0
      rm.. channels.. 3 s. c rm. mv[0] $! a c
      w.
    }
    a z
  }
 
  blend alpha s z r2dx 320
  o output.gif,15

Result:

rock_paper_scissors_water

3 Likes

To those just getting a grasp of this stuff: keep at it! When the moment arrives to do G’MIC doodles, run with it. Ten years on and more, and the delight of seeing where a piece of code might go never wanes. It’s time well spent and — who knows? — you may even come up with something useful.

Here is a variation with 4 colors:

And with 10 colors:

This is making my head spin a little…
It’s kinda funny how those yellow blobs just pop in and out.

BTW, i don’t think i’ll ever understand what’s in the f part of the code, but can you detail what’s happening here ? :
+==[0] 1 +==[0] 2 ==[0] 0

== is shorthand for the eq command. Amusingly, the shorthand is the same length as the command it abbreviates.

+==[0] 1 translates to “duplicate (+) the selected image(s) (here, the first image on the stack) and compare each pixel element (pel) to 1( the eq command’s argument). For those comparisons that result in ‘True’, set 1 for the corresponding pel in the duplicate. Otherwise, (False), set 0”.

For example, find all pels in cameraman that are equal to a value of 177, and normalize for paint programs:

gmic sp cameraman,512 +== 177 n. 0,255

1 Like