# Category Archives: setPixel

## Strange BitmapData Drawing Instructions

Actionscript:
1. // instructions
2. var ins:Array = [0,
3. -1, 100, 200, 3, 100, 0, 50, 1, 100, -1, 100, 150, 0, 50,
4. -1, 160, 200, 0, 50, 3, 50, 2, 50, 3, 50, 0, 50,
5. -1, 220, 200, 0, 50, 3, 50, 2, 50, -1, 270, 150, 3, 50, 2, 50];
6.
7. var canvas:BitmapData = new BitmapData(400,400,false, 0xCCCCCC);
9.
10. var index:int = 0;
11. var penX:int = 0;
12. var penY:int = 0;
13.
15.
17.     var i:int, xp:int, yp:int;
18.     if (ins[index+1] == -1){
19.          index++;
20.         xp = ins[++index];
21.         yp = ins[++index];
22.     }else{
23.         xp = penX;
24.         yp = penY;
25.     }
26.     var dir:int = ins[index];
27.     var leng:int = ins[++index];
28.     for (i = 0; i<leng; i++){
29.         if (dir == 0){
30.             xp += 1;
31.         }else if (dir == 1){
32.             yp += 1;
33.         }else if (dir == 2){
34.             xp -= 1;
35.         }else if (dir == 3){
36.             yp -= 1;
37.         }
38.         canvas.setPixel(xp, yp, 0x000000);
39.      }
40.      penX = xp;
41.      penY = yp;
42.     if (index <ins.length){
44.     }
45. }

I was thinking today about alternative ways to represent drawings and I wrote this snippet while brainstorming. The function read() looks through an array of instructions (ins[]) and draws an image. In this case the letters AS3 are drawn to a Bitmap using setPixel().

The instructions work like this:

The first value of the array is ignored - it can be set to 0, or used to store some other info.
If the next value is a -1, the following two values in the array are used as a sort of moveTo().
This is followed by a direction value 0 = right, 1 = down, 2 = left, 3 = up.
Lastly there is a length value in pixels.

If no -1 is found, the read() function assumes that the value is for a direction.

So to draw a line from (100, 100) to (150, 100) you would write:
`[0, -1, 100, 100, 0, 50]`

To then draw a line down 50 pixels from the endpoint of the previous line you would add 1 (move down), 50 (length 50)... so you to end up with:
`[0, -1, 100, 100, 0, 50, 1, 50]`

and so on...

I'm not sure really where I was going with this, but it was fun to write...

Recently saw some great links making use of Global Illumination/Ambient Occlusion... these ones are from wonderfl posted by keim at Si :
This first example is based on something called AO bench.
one
two
three

and there is something called MiniLight which has been ported to Flex.

## More Messy Code

Actionscript:
1. var size:Number = 800;
2. var canvas:BitmapData = new BitmapData(size,size,false, 0x000000);
4.
5. scaleX = scaleY = .5;
6. var pix:Number = size * size;
7. var scale:Number = 1/(size/3);
8.
9. for (var i:Number = 0; i<pix; i++){
10.        var xp:Number = (i % size);
11.        var yp:Number = int(i / size);
12.        var xt:Number = xp * scale;
13.        var yt:Number = yp * scale;
14.        var ca:Number =  (Math.abs(Math.tan(yt) * Math.pow(Math.sin(xt),3)) * 100 ) % 155;
15.        var cb:Number =  (Math.abs(Math.tan(xt) * Math.pow(Math.sin(yt),3)) * 100)  % 155;
16.        ca|= cb;
17.        canvas.setPixel(xp, yp,  ca <<16 | ca <<8 | ca);
18. }

Another messy code snippet that I e-mailed to myself at some point...

Try replacing line 16 with some of these variations:

```ca &= cb; ca += cb; ca -= cb; ca ^= cb; ca %= cb```

## Random Equation Attractor

Actionscript:
1. [SWF(width = 800, height = 800)]
2. var a:Number = 0.19;
3. var b:Number = .9;
4. var c:Number = 1.3
5. var xn1:Number = 5;
6. var yn1:Number = 0;
7. var xn:Number, yn:Number;
8.
9. var scale:Number =40;
10. var iterations:Number = 20000;
11.
12. function f(x:Number):Number{
13.     // too lazy to simplify this at the moment
14.     return((x + .1 + x * (a - c) * x) / (1.1 + a * (c*c + a*a)  * x * x )) * 1.3;
15. }
16.
17. var canvas:BitmapData = Bitmap(addChild(new Bitmap(new BitmapData(800,800,false,0xEFEFEF)))).bitmapData;
18.
20. function onLoop(evt:Event):void {
21.
22.     canvas.fillRect(canvas.rect, 0xEFEFEF);
23.
24.     c +=  ((stage.stageWidth/2 - mouseX) / 8000 - c) / 2;
25.
26.     xn1 = 0;
27.     yn1 = 0;
28.     for (var i:int = 0; i<iterations; i++){
29.           xn = xn1;
30.           yn = yn1;
31.
32.           xn1 = -xn - a + c +  f(yn);
33.           yn1 = -xn + c * f(xn * yn);
34.           canvas.setPixel( 380 + xn1 * scale, 450 + yn1 * scale, 0x000000);
35.     }
36. }

I was randomly messing around with strange attractors a few weeks back and this is one of the better results.... I arbitrarily altered equations until I got a nice result. You can move your mouse left and right to alter some of the params. Here is what it looks like when your mouse is in the middle of the screen:

Actionscript:
1. var canvas:BitmapData=new BitmapData(400,400,false,0x000000);
3.
4. var a:Number=-1.21;
5. var r:Rectangle=new Rectangle(0,0,3,5);
6. var halfWidth:Number=canvas.width/2;
7. var halfHeight:Number=canvas.height/2;
8.
9. render();
10.
11. function render():void{
12.     for (var x:Number = -2; x<=2; x+=.01) {
13.         for (var y:Number = -2; y<=2; y+=.02) {
14.
15.             // equation from : http://en.wikipedia.org/wiki/Bicuspid_curve
16.             //(x^2 - a^2) * (x - a)^2 + (y^2 - a^2) * (y^2 - a^2) = 0
17.
18.             // unpoptimized:
19.             // var e:Number = (x*x - a*a) * (x-a)*(x-a) + (y*y-a*a) * (y*y-a*a);
20.             // optimized:
21.             var x_a:Number=x-a;
22.             // factoring: x^2 - a^2 = (x + a) * (x - a)
23.             var y2_a2:Number =  (y + a) * (y - a);
24.             var e:Number = (x + a) * x_a * x_a *  x_a +  y2_a2 * y2_a2;
25.
26.                 r.x=halfWidth+y*50;
27.                 r.y=halfHeight-x*100;
28.                 var col:Number = e * 50;
29.                 if (col <10){
30.                     col = Math.abs(col) + 70;
31.                     canvas.fillRect(r, col <<16 | col <<8 | col );
32.                 }
33.         }
34.     }
35. }

This is a variation on a post from a little while back.... it plots a modified Bicuspid that resembles a tooth:

Actionscript:
1. var canvas:BitmapData=new BitmapData(200,200,false,0x000000);
3. scaleX=scaleY=2;
4. var pixNum:int=canvas.width*canvas.height;
5.
6. var xp:Vector.<int> = new Vector.<int>();
7. var yp:Vector.<int> = new Vector.<int>();
8. var radius:Vector.<Number> = new Vector.<Number>();
9. var theta:Vector.<Number> = new Vector.<Number>();
10. for (var i:int = 0; i<pixNum; i++) {
11.     xp.push(i % 200);
12.     yp.push(int(i / 200));
13.     var dx:Number=100-xp[i];
14.     var dy:Number=100-yp[i];
15.     theta.push(Math.atan2(dy, dx));
16.     radius.push(Math.sqrt(dx * dx + dy * dy)/20);
17. }
18.
20. function onLoop(evt:Event):void {
21.     canvas.lock();
22.     var n:Number = mouseX / 100;
23.     for (var i:int = 0; i<pixNum; i++) {
24.         var swirl:Number = 1+Math.sin(6*Math.cos(radius[i]) -n*theta[i]);
25.         canvas.setPixel(xp[i], yp[i],  Math.abs(255 - swirl * 255));
26.     }
27.     canvas.unlock();
28. }

This snippet creates a swirl gradient. While this snippet is not highly optimized, it does implement a basic optimization technique ... I cache some repetitive calculations in Vectors and then use them on the main loop.

I got the function for a swirl gradient from mathworld...

## Utils3D.projectVectors() & 100,000 pixels

Actionscript:
1. var matrix:Matrix3D = new Matrix3D();
2.
3. const PARTICLE_NUM:int = 100000;
4. var verts:Vector.<Number> = new Vector.<Number>();
5. var pVerts:Vector.<Number> = new Vector.<Number>();
6. var uvts:Vector.<Number> = new Vector.<Number>();
7.
8. for (var i:int = 0; i<PARTICLE_NUM; i++){
9.     verts.push(Math.random()*250 - 125);
10.     verts.push(Math.random()*250 - 125);
11.     verts.push(Math.random()*250 - 125);
12.
13.     pVerts.push(0), pVerts.push(0);
14.     uvts.push(0), uvts.push(0), uvts.push(0);
15. }
16.
17. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
19. var dx:Number=0;
20. var dy:Number=0;
21.
23. function onLoop(evt:Event):void {
24.
25.     dx += (mouseX - dx)/4;
26.     dy += (mouseY - dy)/4;
27.
28.     matrix.identity();
29.     matrix.appendRotation(dy,Vector3D.X_AXIS);
30.     matrix.appendRotation(dx,Vector3D.Y_AXIS);
31.     matrix.appendTranslation(200, 200, 0);
32.
33.     Utils3D.projectVectors(matrix, verts, pVerts, uvts);
34.
35.     canvas.lock();
36.     canvas.fillRect(canvas.rect, 0x000000);
37.         var leng:int = pVerts.length;
38.     for (var i:int = 0; i<leng; i+=2){
39.         canvas.setPixel( pVerts[i], pVerts[i + 1], 0xFFFFFF);
40.     }
41.     canvas.unlock();
42. }

The above shows an easy way to use Utils3D.projectVectors() to move some pixels around in 3D. Since the 3D math is done behind the scenes by the flash player it runs quite fast...

Also posted in 3D, BitmapData, Vector, matrix | Tagged , | 3 Comments

## Supershapes / Superformula

Actionscript:
1. // Superformula (equations from):
3. // http://en.wikipedia.org/wiki/Superformula
4. const TWO_PI:Number = Math.PI * 2;
5. function superShape(a:Number, b:Number, m:Number, n1:Number, n2:Number, n3:Number, pnt:Point, scale:Number):void{
6.     var r:Number = 0
7.     var p:Number = 0;
8.     var xp:Number = 0, yp:Number = 0;
9.     while(p <= TWO_PI){
10.         var ang:Number = m * p / 4;
11.         with(Math){
12.             r = pow(pow(abs(cos(ang) / a), n2) + pow(abs(sin(ang) / b), n3),-1/n1);
13.             xp = r * cos(p);
14.             yp = r * sin(p);
15.         }
16.         p += .01;
17.         canvas.setPixel(pnt.x + xp *scale, pnt.y + yp * scale,  0xFFFFFF);
18.      }
19. }
20. // test it out:
21. var canvas:BitmapData = new BitmapData(700,600,false, 0x000000);
23.
24. superShape(1, 1, 5, 23, 23, 23, new Point(100,80), 30);
25. superShape(1, 1, 5, 13, 13, 3, new Point(200,80), 30);
26. superShape(1, 1, 8, 3, 13, 3, new Point(300,80), 30);
27. superShape(10,8, 16, 30, 13, 3, new Point(450,80), 30);
28. superShape(1,1, 1, .5, .5, .5, new Point(100,190), 100);
29.
30. for (var i:int = 0; i <150; i++){
31.   superShape(1,1, 2, 1+i/800, 4, 8-i * .1, new Point(550,350), 50);
32. }
33. for (i = 0; i <20; i++){
34.   superShape(1.1,1.2, 6, 2 + i , 4, 9 - i, new Point(200,350), 50);
35. }

The above snippet demos a function that will draw Supershapes using the Superformula...

From wikipedia:
The Superformula appeared in a work by Johan Gielis. It was obtained by generalizing the superellipse, named and popularized by Piet Hein...

Here is the result of the above code:

You can read more about the Superformula here in the original paper by Gielis.

wikipedia entry...

3d Supershapes by Paul Bourke

## Slow Circle Drawing

Actionscript:
1. var canvas:BitmapData = new BitmapData(400,400,false, 0xCCCCCC);
3.
5. function onLoop(evt:Event):void {
6.     canvas.fillRect(canvas.rect, 0xCCCCCC);
7.
8.     var r:Number = Math.abs(200 - mouseX);
9.     var r2:Number = r * r;
10.     var inc:Number = 1 / r;
11.     var xp:Number = .00000001;
12.     var yp:Number = -r;
13.     while(yp<r){
14.           var y:Number = 200 + yp;
15.           yp += xp * inc;
16.           xp = Math.sqrt(r2 - yp * yp);
17.           canvas.setPixel(200 + xp, y, 0x000000);
18.           canvas.setPixel(200 - xp, y, 0x000000);
19.      }
20. }

A slow way to draw circles using setPixel().

Actionscript:
1. var canvas:BitmapData = new BitmapData(400,400,false, 0xCCCCCC);
3.
5. function onLoop(evt:Event):void {
6.     canvas.fillRect(canvas.rect, 0xCCCCCC);
7.     var r:Number = Math.abs(200 - mouseX);
8.     var r2:Number = r * r;
9.     var inc:Number = 1 / r;
10.     var xp:Number = .000001;
11.     var yp:Number = -r;
12.     while(yp <= 0){;
13.          var x1:Number = 200 + xp;
14.          var y1:Number = 200 + yp
15.          var x2:Number = 200 - xp;
16.          var y2:Number = 200 - yp;
17.          canvas.setPixel(x1, y1, 0x000000);
18.          canvas.setPixel(x1, y2, 0x000000);
19.          canvas.setPixel(x2, y1, 0x000000);
20.          canvas.setPixel(x2, y2, 0x000000);
21.           yp += xp * inc;
22.           xp = Math.sqrt(r2 - yp * yp);
23.      }
24. }

Little better, still slow.

I was brainstorming about a few things today and somehow these two slow circle drawing algorithms popped out. These are pretty useless compared to some of the famous algorithms I've posted in the past. Kind of interesting nevertheless.

## Closed Catmull-Rom

Actionscript:
1. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
3.
4. var pnts:Array = new Array();
5. // make control points
6. for (var i:int = 0; i<5; i++){
7.     var t:Number = i * 72 * Math.PI /180;
8.     pnts.push(dot(200 + 100 * Math.cos(t),200 +100 * Math.sin(t)));
9. }
10.
12. function onLoop(evt:Event):void {
13.     canvas.lock();
14.     canvas.fillRect(canvas.rect, 0x000000);
15.     curve(pnts);
16.     canvas.unlock();
17. }
18.
19. function tangent(pk1:Sprite, pk_1:Sprite){
20.     return new Point((pk1.x - pk_1.x) / 2, (pk1.y - pk_1.y) / 2);
21. }
22.
23. // all math from http://en.wikipedia.org/wiki/Cubic_Hermite_spline
24. function curve(p:Array, res:Number=.03):void{
25.     var px:Number = 0;
26.     var py:Number = 0;
27.     var pIter:int = p.length - 1;
28.     var m:Array = [];
29.
30.     m[0] = tangent(p[1] ,  p[pIter]);
31.     for (var i:int = 1; i<pIter; i++){
32.         m[i] = tangent(p[i + 1], p[i - 1]);
33.     }
34.     m[pIter] = tangent(p[0],p[pIter-1]);
35.
36.     for (var t:Number = 0; t <1; t+=res){
37.          var t_2:Number = t * t;
38.          var _1_t:Number = 1 - t;
39.          var _2t:Number = 2 * t;
40.
41.          var h00:Number =  (1 + _2t) * (_1_t) * (_1_t);
42.          var h10:Number =  t  * (_1_t) * (_1_t);
43.          var h01:Number =  t_2 * (3 - _2t);
44.          var h11:Number =  t_2 * (t - 1);
45.
46.          for (var k:int = 0; k <pIter; k++){
47.              var k1:int = k + 1;
48.              var pk:Sprite = p[k];
49.              var pk1:Sprite = p[k1];
50.              var mk:Point = m[k];
51.              var mk1:Point = m[k1];
52.              px = h00 * pk.x + h10 * mk.x + h01 * pk1.x + h11 * mk1.x;
53.              py = h00 * pk.y + h10 * mk.y + h01 * pk1.y + h11 * mk1.y;
54.              canvas.setPixel(px, py, 0xFFFFFF);
55.          }
56.           pk = p[k];
57.           pk1 = p[0];
58.           mk = m[k];
59.           mk1= m[0];
60.
61.           px = h00 * pk.x + h10 * mk.x + h01 * pk1.x + h11 * mk1.x;
62.           py = h00 * pk.y + h10 * mk.y + h01 * pk1.y + h11 * mk1.y;
63.           canvas.setPixel(px, py, 0xFFFFFF);
64.     }
65. }
66.
67. // draggable dot
68. function dot(xp:Number, yp:Number, col:uint = 0xFF0000, rad:Number=4):Sprite {
69.     var s:Sprite = Sprite(addChild(new Sprite));
70.     s.x = xp;
71.     s.y = yp;
73.     s.buttonMode = true;
75.     return s;
76. }
77. function onDrag(evt:MouseEvent):void {
78.     evt.currentTarget.startDrag()
79. }
81. function onUp(evt:MouseEvent):void{
82.     stopDrag();
83. }

This a variation on a post from a few days ago. This shows how to create a closed Catmull Rom spline.

See the other Catmull-Rom related Posts

Also posted in Math, graphics algorithms | Tagged , | 2 Comments