Archive for September, 2008

Eyes & Code Drawing

Tuesday, September 30th, 2008

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:
  1. this.graphics.lineStyle(0,0);
  2.  
  3. // graphics, x position, y position, detaill, xRadiusMax, yRadiusMax, xRadiusMin, yRadiusMin, smoothness
  4.  
  5. roughCircle(this.graphics, 200,200, 180, 100, 100, 50,50);
  6.  
  7. function roughCircle(g:Graphics, xx:Number, yy:Number, detail:int, r1:Number, r2:Number, r3:Number, r4:Number, smooth:Number=15):void {
  8.     var xp:Number, yp:Number;
  9.     var rx:Number=r3 + Math.random()*(r1-r3);
  10.     var ry:Number=r4 + Math.random()*(r2-r4);
  11.  
  12.     var theta:Number = Math.random()*6.28;
  13.     var inc:Number = Math.PI * 2 / detail;
  14.  
  15.     for (var i:int = 0; i<detail; i++) {
  16.  
  17.         rx += ( (r3 + Math.random() * (r1-r3)) - rx) / smooth;
  18.         ry += ( (r4 + Math.random() * (r2-r4)) - ry) / smooth;
  19.         theta += inc;
  20.         xp = xx + rx * Math.cos(theta);
  21.         yp = yy + ry * Math.sin(theta);
  22.         if ( i == 0) {
  23.             g.moveTo(xp, yp);
  24.         } else {
  25.             g.lineTo(xp, yp);
  26.         }
  27.     }
  28. }

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:
  1. this.graphics.lineStyle(0,0,.5);
  2. var inc:int= 20;
  3. for (var i:int = 0; i<4; i++) {
  4.     for (var j:int = 0; j<5; j++) {
  5.         roughCircle(this.graphics, 50 + j * 100,50 + i* 100, 180, 50, 50, 25,25, inc);
  6.         inc--;
  7.     }
  8. }
  9.  
  10. for (i = 0; i<100; i++) {
  11.     this.graphics.lineStyle(0,0, (1 - (i / 100)/2) - .5);
  12.     var r = 150 - i;
  13.     roughCircle(this.graphics, 150+i/2,550+i/2, 180, r,r, r-30,r-30);
  14. }
  15.  
  16. for (i = 0; i<50; i++) {
  17.     this.graphics.lineStyle(0,0, 1 - (i / 100)-.4);
  18.     r = 100 - i*2;
  19.     roughCircle(this.graphics, 400,500+i*3, 180, r,r/4, r-30,r-30);
  20. }

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...

Microscopy Sketch (emboss)

Monday, September 29th, 2008

I've been tweaking a programmatic sketch for the past couple days... It contains three cell-like elements that randomly move around the screen. I've been trying to decide how to take it further...



Click above image to view flash version

To take it farther I just want to add some additional elements and maybe change the cells behavior a bit - something more than just floating around randomly - I'd like to have them eat other little cells - or change/die over time...

A few years back I wrote something like this in director. It runs super fast now because I put the framerate at 999... too lazy to go through my archives and dig up the .dir... so here's a still:

Using a convolution filter to create an emboss works nicely, but is very very slow. You can create an emboss effect by using copyPixels(), draw(), blend modes and a BlurFilter:

Actionscript:
  1. var canvas:BitmapData = new BitmapData(500, 500, true, 0xFFFFFFFF);
  2. var color:BitmapData= new BitmapData(500, 500, true, 0x81666666);
  3. var over:BitmapData = new BitmapData(500, 500, true, 0xFF000000);
  4. addChild(new Bitmap(canvas, "auto", true));
  5.  
  6. var circle:Shape = new Shape();
  7. circle.graphics.beginFill(0xFFFFFF,1);
  8. circle.graphics.drawCircle(0,0,50);
  9.  
  10.  
  11. var m:Matrix = new Matrix();
  12.  
  13. m.tx = 0;
  14. m.ty = 1;
  15.  
  16. addEventListener(Event.ENTER_FRAME, onLoop);
  17. function onLoop(evt:Event):void {
  18.  
  19.     circle.x = mouseX;
  20.     circle.y = mouseY;
  21.     canvas.draw(circle, circle.transform.matrix);
  22.  
  23.     canvas.copyPixels(color, color.rect, new Point(0,0), null, null, true);
  24.    
  25.     over.copyPixels(canvas, canvas.rect, new Point(0,0), null, null, true);
  26.  
  27.     canvas.draw(over, m, null, BlendMode.SCREEN);
  28.     over.applyFilter(over, over.rect, new Point(-2,-2), new BlurFilter(10,10,1));
  29.  
  30.     canvas.draw(over, m, null, BlendMode.SUBTRACT);
  31. }

I also did this kind of emboss in processing a few years back. The meat of that looked like this:

JAVA:
  1. ellipse(mouseX,mouseY,60,60);
  2.  
  3.   for(int i=0; i<(width*height)-offset; i++){
  4.     pixels[i] = ((int)((~pixels[i] & 0xff)*0.25f + (pixels[i+offset] & 0xff) * 0.75f)*65793);
  5.   }

City From Fire (Cellular Automata)

Saturday, September 27th, 2008

This is another sketch dug up from my Cellular Automata folder. As I mentioned in my previous post about Cellular Automata - I like to base the rules on the color of the current pixel and its neighbors. This example looks like a city being built from fire:





Click either of the above images to view flash version

If you watch this for about 20 or 30 seconds nearly all the fire should disappear - leaving red pixels wandering through gray corridors.

Once you've got a basic template for this type of CA... you can just play with the code. After awhile you can even begin to predict some of the results and really control what your CA does. The following code snippet should help you get started... it creates 300 vertically wandering red pixels:

Actionscript:
  1. // current pixel
  2. var pix:uint;
  3.  
  4. var size:Number = 200;
  5. // read from the pixels BitmapData and write to the buffer BitmapData
  6. var pixels:BitmapData = new BitmapData(size,size, false, 0x000001);
  7. var buffer:BitmapData = new BitmapData(size,size, false, 0x000001);
  8.  
  9. var frame:Bitmap = new Bitmap(pixels);
  10. addChild(frame);
  11.  
  12. frame.scaleX= 2;
  13. frame.scaleY = 2;
  14.  
  15. // place 300 red pixels
  16. for (var i = 0; i<300; i++) {
  17.     buffer.setPixel(100 + Math.random()*40-20, 100 + Math.random()*40-20, 0xFF0000);
  18. }
  19.  
  20. addEventListener(Event.ENTER_FRAME, onLoop);
  21. function onLoop(evt:Event):void {
  22.     for (var i:int = 0; i<size; i++) {
  23.         for (var j:int = 0; j<size; j++) {
  24.             pix = pixels.getPixel(j, i);
  25.             // add additional logic here:
  26.             if (pix == 0xFF0000) {
  27.                   buffer.setPixel(j, i, 0x000001);
  28.                   buffer.setPixel(j, i+Math.random()*4-2, 0xFF0000);
  29.                   // and here
  30.             }
  31.         }
  32.     }
  33.     pixels.draw(buffer);
  34. }