I haven't had too much time to play around with Nim and other technology since I've had to move to accept a new job, but I decided to take some time this weekend to write a tutorial on how to do code "hot loading," in Nim. I'm pretty bad at making the first link in my blog posts link to what I'm actually talking about, so for a change it's right here.
As of the past year Glitchet has been one of my favorite parts of the week. It's a mini newsletter that covers all sort of futurism and computer arts thing that I'm interested in. A While back (seven months actually), I contacted the curator of webzine and told him he should do an article on Random Art. I didn't hear back from him until a few days ago.
He asked me if I was willing to write a piece on how it works. Everything was fresh in my mind from my Nim port of Random Art, so I agreed. Over the weekend I came up with this. It gives you a simple overview of how the process works and where these pretty pictures come from. If you don't understand anything, I'm sure you'll be able to grasp something at least.
So I haven't updated it in about 4-5 months. I think that It's time that I get rid of the "hiatus," marker on the side and say that it's officially over. I was planning on covering things like SSL and async Sockets, and maybe exploring some 3rd party libraries. But I think it might be better to say that it's officially over rather than to have this monkey on my back. I have a new job to deal with and my interest in C# has waned a little.
If you would like to, you can read some more details about the conclusion here. For those of you who never knew about it, you can start the course here.
The ride was fun and educational to me as well. Thanks.
It seems like every one to two weeks I've been writing a new package for Nim. I've been playing around with the JavaScript target. There is some basic stuff there in the dom module for HTML manipulation but I noticed something very important was missing; the canvas
tag. So well, I added a thin wrapper for it (GitHub mirror). It's available under the html5_canvas
package in nimble.
When I first heard about HTML5 and read the spec a little, I think one of the most important things that was added was the canvas
tag, and along with it a JavaScript API for all sorts of drawing operations. Interactive content for the web that was being made with technologies like Flash and Java (applets) could now closer to the browser level (and have better performance to boot)!
The only thing is that I don't really like writing JS code; it's my least favorite language out there. But you know we live in a time where you don't have to write JavaScript to write JavaScript anymore! While Nim's JS backend is still marked as experimental I think that its nice enough where we can still make some cool stuff with it.
I tried to keep the API as close as possible to the one listed in the Mozilla docs. Though I did have to make a few changes. One of those in particular are the fillStyle
and strokeStyle
getters and setters. The problem with these two fields of CanvasRenderingContext2D
is that they can be one of any three different types (see here). Nim being a strongly typed language wouldn't let me put those properties right under the type ... object
definition. Luckily though there is still a way to keep the API so it looks like we're setting a field instead of having to add a setFillStyle()
proc. Taken from the source, look a this:
proc `fillStyle=`*( ctx: CanvasRenderingContext2D; color: cstring ) {.inline.} = {.emit: [ctx, ".fillStyle=", color, ";"].} # Can do this now! ctx.fillStyle = rgb(255, 0, 255)
But as for the getters I had to do this:
proc fillStyleColor*(ctx: CanvasRenderingContext2D): cstring {.inline.} = {.emit: [result, "=", ctx, ".fillStyle;"].}
There's one for Gradient
and one for Pattern
as well.
For some extra fun, I ported over my 3D Canvas Cube from Dart (another language that compiles to JS). I've put the source up in my toybox repo. What's also pretty cool is that the compressed JS output from dart2js
was about 90 kilobytes, where as Nim's compressed JS is around 20 kilobytes! Originally when when did full imports (i.e. import math
) I was getting 124 KB compressed, but when I changed to selective imports (from math import Pi, sin, cos, floor
) I was able to drastically reduce the size.
I was able to get the animation to work by adding a mini proc to wrap JS's setTimeout()
function:
proc setTimeout(function: proc(); ms: float) = {.emit: ["setTimeout(", function, ",", ms, ");"].}
If you're bored with 2D graphics and want to do something 3D in Nim (and in the browser), take a look at stisa's nice WebGL wrapper.
Here is the link to the repo for this again (GitHub mirror). It's also on nimble under html5_canvas
. Have fun!
Edit (Jan 30th, 2017): I written an article on how Random Art works. You can read it here.
Have you ever heard of Random Art before? If you don't know what it is, the short and skinny is that it's a program that will generate some really stunning images using a randomly generated math equation. That's what the image above was made with. The original program was written by Andrej Bauer. The Random Art website uses an OCaml program that been compiled to JavaScript. Unfortunately the source for that is not publicly posted (which is a shame because it makes some of the best pictures), but a simple Python implement is available. Going off from that, I decided it port it over to Nim and add support for rending with OpenGL (and make a few other changes I see fit).
Well... actually I ported that to C++ (& Qt) first about a year ago, then I did another port over to C# four months later. The C# one was a little more interesting because it was a distributed rendering system leveraging cloud services and RabbitMQ; I ended up using it on a film I was working on. Pretty cool. Those... I don't really feel comfortable sharing the source to right now. But I'll give you a Nim implementation instead. : P
You can find the application over here on GitLab (or GitHub if you prefer it). To compile the thing, your going to need GLFW installed as well. It can run into two modes: CPU bounding rendering and GPU (via OpenGL). There is a lot more info the in the Readme, but here is the usage message:
Usage: ./random_art [input] [options..] input : a path to an equation file, or provide `stdin` to read input from standard input Options: -r, --renderer : cpu | opengl render on the CPU or with a GPU (using OpenGL) -s, --size : <width>x<height> the dimension of the render, must be a positive int -b, --bounds : <xMin>,<xMax>,<yMin>,<yMax> the bounds to use to render, must be a float -o, --output : <filename>.png the file to save the render as, must end with .png
If you run the application without providing an equation, it will think up one for you. Writing your own equations has this Scheme-like syntax. It's pretty easy to understand, but also to parse. The equation below makes the image to the right.
(mul (var y) (mod (sum (var x) (var y) ) (const 1 0.7 -0.1 0.95) ) )
I plan on working on this some more down the road. You can already see some of my changes showing up (e.g. an alpha value). I'll keep you guys posted. Once again, the code is available here (GitHub mirror).