beef331 / website

Code for the official Nim programming language website
https://nim-lang.org
18 stars 1 forks source link

Nanim #33

Closed EriKWDev closed 2 years ago

EriKWDev commented 2 years ago

Name: Nanim

Author: ErikWDev

Posting:

For the last year I've had a hobby of creating smooth animations / motion graphics and uploading them to my instagram. I did it daily for a very long period and while doing it I developed a library with which I could create these animations, and this month I decided to release it into the public under the MIT license: https://github.com/EriKWDev/nanim

I've snazzily summarized it as "an easy-to-use framework to create smooth GPU-accelerated animations that can be previewed live inside a glfw window and, when ready, rendered to videos at an arbitrary resolution and framerate." 'easy-to-use' is obviously a biased statement coming from the creator, but It has been perfect for my needs!

I was heavily inspired by 3b1b's wonderful manim which is a much more sophisticated piece of software that, among other things, use TeX to render beautiful text. It is written in Python and used to be based on Cairo, but nowadays it uses opengl.

Anyway, I love Nim so that's the language I wanted to use for my project. I use staticglfw with opengl to create a window and context and then using some nim nanovg bindings I can draw cool vector graphics. Finally, using osproc and streams I can manage a FFmpeg process and pipe frames into it to generate a smooth video.

I did not spend much time up front designing the inner workings of the library, but rather developed it as I created more animations. When I wanted to try something different, I reworked the core, added more easings and entities and streamlined the workflow.

The basic scene is constructed like this:

import nanim

proc myScene(): Scene =
  let scene = newScene()

  # ...add and anaimate entities

  return scene

when isMainModule:
  render(myScene)

But that's not very fun, there's no animations nor shapes! To just give some sneak peaks of what is possible with nanim, here are some samples that I've created:

Green Spirals Rainbow
Nachos Candy
Green Spinners Wobble
Arcs Particles

If you have instagram, I have a lot more posted over there!

Here is a more complete example utilizing many parts of nanim to construct an interesting animation:

import nanim

proc daily094Scene(): Scene =
  let scene = newScene()
  scene.randomize()

  # We can parse colors from a coolors palette!
  var colors = colorsFromCoolors("https://coolors.co/cfdbd5-e8eddf-f5cb5c-242423-333533")
  colors.shuffle()

  let bg = colors[0]

  scene.setBackgroundColor(bg)
  colors.del(0)

  for i in 0..60:
    # Entities are created using new<Entity>(), such as newDot(), newRect(),
    # newSquare(), newHexagon(), newPolygon(), newArc(), newText() and many more!
    let d = newDot(rand(6.0..190.0))

    # entities can then be manipulated with procs like .fill(), .stroke(),
    # .moveTo(), .rotate(), .move(), .scale(), .scaleTo()
    d.fill(colors.sample())
    d.moveTo(rand(0.0..1000.0), rand(0.0..1000.0))

    # In order to render an entity, we have to add it to the scene
    scene.add(d)

    # Tracks is a concept in nanim that can be used to create multiple timelines.
    # Think of them like rows of stacked videos in a video editor. By sleeping a
    # random amount at the start of each track, we can create a staggering effect.
    scene.onTrack i:
      scene.sleep(rand(0.0..4000.0))

      # all the previous <entity>.<changeProperty>() return a Tween which can be
      # animated using scene.play(<Tween>). Tweens have a duration and easing and
      # can be changed using .with(duration=<duration>, easing=<easing>)
      scene.play(d.scaleTo(1.5), d.fadeOut())
      scene.play(d.scaleTo(0.0).with(duration=0.0))
      scene.play(d.scaleTo(1.0), d.fadeIn())

  return scene

when isMainModule:
  # Finally, we render the scene. If --render is provided as arguments, the animation
  # will actually be rendered to a video through FFmpeg. Otherwise it is rendered in
  # realtime in a window.
  render(daily094Scene)

This is the resulting window:

example

The GIF obviously doesn't do the smoothness justice, so here is a rendered, smooth version

I've always used programming as an outlet for my creativity. Both through challenging logical problems, but as well through more expressive and colorful forms of creativity like with nanim. Nim has not only allowed me to do this in a streamlined and easy to read way, but with great computational performance and development productivity.

I hope this post might inspire you to create something creative with Nim -- maybe even dare try out nanim? Wether you do or not, I hope you have a great day. Thanks for reading.

narimiran commented 2 years ago

Hmmm, should this maybe be a separate "guest post" on our blog? This way, @EriKWDev, you could go into more detail about this awesome project.

Here is one example of such a post: https://nim-lang.org/blog/2017/05/25/faster-command-line-tools-in-nim.html

EriKWDev commented 2 years ago

Hmmm, should this maybe be a separate "guest post" on our blog?

That sounds awesome :) I wouldn't mind going a little bit more into the details, but I don't really want this to be a too technical post. The details that I would add in a longer post would probably be some more examples that are simpler each with one more gif. I might write something more technical, but would probably put that on the repo and point to that.

Where should that issue go? Should I edit this one or somewhere else?

narimiran commented 2 years ago

I don't really want this to be a too technical post. The details that I would add in a longer post would probably be some more examples that are simpler each with one more gif.

This sounds good.

Where should that issue go? Should I edit this one or somewhere else?

Ideally, you would open a pull request on our website repo: https://github.com/nim-lang/website/pulls and add your article to _posts: https://github.com/nim-lang/website/tree/master/jekyll/_posts In that directory you can see other posts to guide you, and once you submit your PR, I can review it and/or make changes if necessary.

EriKWDev commented 2 years ago

Very well, I will do that!

I'm not very familiar with Ruby, but I tried installing jekyll and gem to run the website code yesterday, but couldn't get it up and running to preview.

I'll make a more serious attempt again and make a PR to the _posts dir :)

I use MarkDown tables here to align the gifs. Are there any known problems with rendering them on the website or should it be fine?

EriKWDev commented 2 years ago

Also, should I perhaps close the issue here then..?

EriKWDev commented 2 years ago

@narimiran All the gifs are currently hosted in third-party-land, but I see that there is a assets folder on the website.

Would it be OK for me to create a folder there and put the gifs there instead? I see a folder for this-month-with-nim, but no general one for posts.

narimiran commented 2 years ago

Would it be OK for me to create a folder there and put the gifs there instead?

Yes. You can create a directory here: https://github.com/nim-lang/website/tree/master/jekyll/assets/news/images

Are there any known problems with rendering them on the website or should it be fine?

No known problems, but who knows... :D

I'm not very familiar with Ruby, but I tried installing jekyll and gem to run the website code yesterday, but couldn't get it up and running to preview.

If you don't manage to do it, just write a markdown file like you would do it normally, and once the PR is submitted, I can run it on my machine to see if everything works properly.