It's odd, every time I start messing with recursive functions for drawing plants and trees I always end up getting sidetracked.... This time around, after getting some pretty nice looking trees (will post about them sometime soon) I stumbled upon an interesting (and simple) way to get programmatic lines and curves to look a bit more hand drawn... After isolating the technique and ripping it out of my tree generating program I created these generative eyes:
Click any of the above images to view the flash version
I rendered out a few larger images and put them up on flickr here
This isn't the first time I've coded eyes... or at least, not the first time I've code an eye. A few years back I programmed an eye in processing... you can see it here. I was never totally satisfied with the processing eye... I sort of gave up on it... I wanted to make it more photorealistic somehow, but never got around to it...
DRAWING + PROGRAMMING
There are certain things that people just automatically draw without thinking about it... for me these are:
1) bald old man heads
2) ears
3) hands
4) eyes
5) teeth
possible a few more, but the above 5 are the main ones...
Drawing these things for me is pretty much automatic - and I never get tired of it. For a long time I wasn't able to combine programming and drawing, but after I created the daily log - I was occasionally able to combine drawings and programming - One of these programs was my first real OpenGL C++ program the combination project. Lately, with vCanvas and the technique I used for the above eyes - the combination of drawing and programming has been much more organic...
ROUGH CIRCLE
The eyes are built with the use of one function:
Actionscript:
-
this.graphics.lineStyle(0,0);
-
-
// graphics, x position, y position, detaill, xRadiusMax, yRadiusMax, xRadiusMin, yRadiusMin, smoothness
-
-
roughCircle(this.graphics, 200,200, 180, 100, 100, 50,50);
-
-
function roughCircle(g:Graphics, xx:Number, yy:Number, detail:int, r1:Number, r2:Number, r3:Number, r4:Number, smooth:Number=15):void {
-
var xp:Number, yp:Number;
-
var rx:Number=r3 + Math.random()*(r1-r3);
-
var ry:Number=r4 + Math.random()*(r2-r4);
-
-
var theta:Number = Math.random()*6.28;
-
var inc:Number = Math.PI * 2 / detail;
-
-
for (var i:int = 0; i<detail; i++) {
-
-
rx += ( (r3 + Math.random() * (r1-r3)) - rx) / smooth;
-
ry += ( (r4 + Math.random() * (r2-r4)) - ry) / smooth;
-
theta += inc;
-
xp = xx + rx * Math.cos(theta);
-
yp = yy + ry * Math.sin(theta);
-
if ( i == 0) {
-
g.moveTo(xp, yp);
-
} else {
-
g.lineTo(xp, yp);
-
}
-
}
-
}
If you run that in your timeline you'll get one roughly drawn circle... Not all that interesting, but the potential begins to become obvious if you just play with it for a few minutes:
The above image was generated with the roughCircle() function and this extra messy code:
Actionscript:
-
this.graphics.lineStyle(0,0,.5);
-
var inc:int= 20;
-
for (var i:int = 0; i<4; i++) {
-
for (var j:int = 0; j<5; j++) {
-
roughCircle(this.graphics, 50 + j * 100,50 + i* 100, 180, 50, 50, 25,25, inc);
-
inc--;
-
}
-
}
-
-
for (i = 0; i<100; i++) {
-
this.graphics.lineStyle(0,0, (1 - (i / 100)/2) - .5);
-
var r = 150 - i;
-
roughCircle(this.graphics, 150+i/2,550+i/2, 180, r,r, r-30,r-30);
-
}
-
-
for (i = 0; i<50; i++) {
-
this.graphics.lineStyle(0,0, 1 - (i / 100)-.4);
-
r = 100 - i*2;
-
roughCircle(this.graphics, 400,500+i*3, 180, r,r/4, r-30,r-30);
-
}
The messiness of this code is actually important... when I'm "drawing" or "sketching" with code I'm not thinking about putting i/2 into a variable for readability and speed reasons... I'm thinking... "oh, the circles should be offset on the x a little less than i every iteration." Same with weird things like this.. 1 - (i / 100)-.4 ... just achieved quickly through trial and error... heh, this is worse (1 - (i / 100)/2) - .5...