Monthly Archives: July 2009

Sphere of Squares

Actionscript:
  1. [SWF(width = 600, height = 600, backgroundColor=0x000000)]
  2. var squareNum:int  = 1000;
  3. var hw:Number = stage.stageWidth / 2;
  4. var hh:Number = stage.stageHeight / 2;
  5. // verts defines a single square
  6. var verts:Vector.<Number> = Vector.<Number>([-20, 0, 0, 20, 0, 0, 20, 0, 40, -20, 0, 40, -20, 0, 0]);
  7. var cmds:Vector.<int> = Vector.<int>([1,2,2,2,2]);
  8. var tempVerts:Vector.<Number> = new Vector.<Number>();
  9. var newVerts:Vector.<Number> = new Vector.<Number>();
  10. var pVerts:Vector.<Number> = new Vector.<Number>(10 * squareNum);
  11. var uv:Vector.<Number> = new Vector.<Number>(15 * squareNum);
  12. var vectors:Shape = new Shape();
  13. var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0x000000);
  14. addChild(new Bitmap(canvas));
  15. var blurred:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0x000000);
  16. var blur:BlurFilter = new BlurFilter(20,20,1);
  17.  
  18. var m:Matrix3D = new Matrix3D();
  19.  
  20. var radius:Number = 200;
  21. // duplicate the verts array a bunch of times
  22. // each time moving the square to a random place on the
  23. // circumference of a sphere
  24. for (var i:int = 0; i<squareNum; i++){
  25.     m.identity();
  26.     var s:Number = Math.random()*.5 + .5;
  27.     m.appendScale(s, s, s);
  28.     m.appendRotation(90,Vector3D.X_AXIS);
  29.     m.appendTranslation(0, 0, radius);
  30.     m.appendRotation(Math.random()*360,Vector3D.X_AXIS);
  31.     m.appendRotation(Math.random()*360,Vector3D.Y_AXIS);
  32.     m.appendRotation(Math.random()*360,Vector3D.Z_AXIS);
  33.     m.transformVectors(verts,tempVerts);
  34.     newVerts = newVerts.concat(tempVerts);
  35.     cmds = cmds.concat(Vector.<int>([1,2,2,2,2]));
  36. }
  37. newVerts.fixed = pVerts.fixed = uv.fixed = true;
  38. var dx:Number = 0, dy:Number = 0;
  39. var pnt:Point = new Point();
  40. addEventListener(Event.ENTER_FRAME, onLoop);
  41. function onLoop(evt:Event):void {
  42.        dx += (mouseX - dx) / 4;
  43.        dy += (mouseY - dy) / 4;
  44.        m.identity();
  45.        m.appendRotation(dx,Vector3D.Z_AXIS);
  46.        m.appendRotation(dy,Vector3D.X_AXIS);
  47.        m.appendTranslation(hw,hh, 0);
  48.        Utils3D.projectVectors(m, newVerts, pVerts, uv);
  49.        with(vectors.graphics){
  50.            clear();
  51.            beginFill(0xFFFFFF);
  52.            drawCircle(hw, hh, radius+10);
  53.            beginFill(0x000000);
  54.            drawPath(cmds, pVerts, GraphicsPathWinding.NON_ZERO);
  55.        }
  56.        canvas.fillRect(canvas.rect, 0x000000);
  57.        canvas.draw(vectors);
  58.        blurred.copyPixels(canvas, canvas.rect, pnt);
  59.        blurred.applyFilter(blurred,blurred.rect, pnt, blur);
  60.        canvas.draw(blurred, null, null, BlendMode.SCREEN);
  61. }

This snippet is similar to yesterdays post but the visual result is rather different. This one does a little more Matrix3D stuff resulting in a sphere made up entirely of squares. This is obscured by the size of the squares and the fact that they overlap and cut each other up. BitmapData a BlurFilter and a BlendMode give the entire thing a slight glow...


Have a look at the swf here...

Posted in 3D, BitmapData, Vector | Tagged , , , | 12 Comments

transformVectors() and drawPath()

Actionscript:
  1. var squareNum:int  = 100;
  2. // verts defines a single square
  3. var verts:Vector.<Number> = Vector.<Number>([-20, 0, 0, 20, 0, 0, 20, 0, 40, -20, 0, 40, -20, 0, 0]);
  4. var cmds:Vector.<int> = Vector.<int>([1,2,2,2,2]);
  5. var tempVerts:Vector.<Number> = new Vector.<Number>();
  6. var newVerts:Vector.<Number> = new Vector.<Number>();
  7. var pVerts:Vector.<Number> = new Vector.<Number>(10 * squareNum);
  8. var uv:Vector.<Number> = new Vector.<Number>(15 * squareNum);
  9.  
  10. var m:Matrix3D = new Matrix3D();
  11.  
  12. // duplicate the verts array a bunch of times
  13. // each time randomly rotating, scaling and translating it
  14. for (var i:int = 0; i<squareNum; i++){
  15.     m.identity();
  16.     m.appendRotation(Math.random()*360,Vector3D.X_AXIS);
  17.     m.appendRotation(Math.random()*360,Vector3D.Y_AXIS);
  18.     m.appendRotation(Math.random()*360,Vector3D.Z_AXIS);
  19.     var s:Number = Math.random()*2 + .1;
  20.     m.appendScale(s, s, s);
  21.     m.appendTranslation(Math.random()*400 - 200, Math.random()*400 - 200, Math.random()*400 - 200);
  22.     m.transformVectors(verts,tempVerts);
  23.     newVerts = newVerts.concat(tempVerts);
  24.     cmds = cmds.concat(Vector.<int>([1,2,2,2,2]));
  25. }
  26. newVerts.fixed = pVerts.fixed = uv.fixed = true;
  27.  
  28. var dx:Number = 0, dy:Number = 0;
  29. addEventListener(Event.ENTER_FRAME, onLoop);
  30. function onLoop(evt:Event):void {
  31.        dx += (mouseX - dx) / 4;
  32.        dy += (mouseY - dy) / 4;
  33.        
  34.        m.identity();
  35.        m.appendRotation(dx,Vector3D.Z_AXIS);
  36.        m.appendRotation(dy,Vector3D.X_AXIS);
  37.        m.appendTranslation(stage.stageWidth / 2,stage.stageHeight / 2, 0);
  38.  
  39.        Utils3D.projectVectors(m, newVerts, pVerts, uv);
  40.        
  41.        graphics.clear();
  42.        graphics.lineStyle(0,0x000000);
  43.        graphics.drawPath(cmds, pVerts);
  44. }

This is a demo showing how to use transformVectors() and drawPath() together. It creates 100 wireframe squares in 3D:


Have a look at the swf...

Posted in 3D, Graphics, Vector | 2 Comments

Recursive 2D Structure

Actionscript:
  1. [SWF(width = 600, height = 700, frameRate=24)]
  2. var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0xFFFFFF);
  3. addChild(new Bitmap(canvas));
  4.  
  5. var maxBranches:int = 600;
  6. var branches:int = 0;
  7. var startX:Number = 300
  8. makeBranch(startX,690,30,-60, 60);
  9.  
  10. function makeBranch(xp:Number, yp:Number, step:Number, min:Number, max:Number):void {
  11.     var vectors:Shape = Shape(addChild(new Shape()));
  12.     var cX:Number, cY:Number, eX:Number, eY:Number
  13.     var dcX:Number=xp, dcY:Number=yp, deX:Number=xp, deY:Number=yp;
  14.     var theta:Number = (min + Math.random()*(max-min) - 90) * Math.PI / 180;
  15.     cX = xp + step * Math.cos(theta);
  16.     cY = yp + step * Math.sin(theta);
  17.     theta = (min + Math.random()*(max-min)-90) * Math.PI / 180;
  18.     eX = cX + step * Math.cos(theta);
  19.     eY = cY + step * Math.sin(theta);
  20.     var run:Function = function():void{
  21.          dcX +=  (cX - dcX) / 2;
  22.          dcY +=  (cY - dcY) / 2;
  23.          deX +=  (eX - deX) / 8;
  24.          deY +=  (eY - deY) / 8;
  25.          with(vectors.graphics){
  26.               clear();
  27.               beginFill(0xFFFFFF,0.8);
  28.               lineStyle(0,0x000000,0.8);
  29.               moveTo(startX, yp);
  30.               lineTo(xp, yp);
  31.               curveTo(dcX, dcY, deX, deY);
  32.               lineTo(startX, deY);
  33.          }
  34.          if (Math.abs(dcX - cX) <1 && Math.abs(deX - eX) <1 && Math.abs(dcY - cY) <1 && Math.abs(deY - eY) <1){
  35.              canvas.draw(vectors);
  36.              removeChild(vectors);
  37.              if (branches <maxBranches){
  38.                  setTimeout(makeBranch, 10, deX, deY, step - Math.random(), -90, 90);
  39.                  branches++;
  40.                  if (int(Math.random()*2) == 1){
  41.                     setTimeout(makeBranch, 10, deX, deY, step - Math.random()*3, -90, 90);
  42.                     branches++;
  43.                  }
  44.              }
  45.          }else{
  46.              setTimeout(arguments.callee,  1000 / 24);
  47.          }
  48.     }();
  49. }

This snippet uses a technique similar to what you might use to create a recursive tree. A bit of additional logic is added for bezier branches, filled shapes and animation.

WARNING: may run slow on older machines

Have a look at the swf...

Posted in BitmapData, bezier, functions, misc, motion | Tagged , , | 7 Comments

Smudge Tool #1

Actionscript:
  1. [SWF(backgroundColor = 0xCCCCCC)]
  2. var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,true, 0xFFFFFFFF);
  3. addChild(new Bitmap(canvas));
  4.  
  5. var loader:Loader = new Loader();
  6. loader.load(new URLRequest("http://actionsnippet.com/wp-content/chair.jpg"));
  7. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
  8. function onComplete(evt:Event):void{
  9.     canvas.draw(loader);
  10. }
  11.  
  12. var brush:Shape = new Shape();
  13. var diameter:Number = 120;
  14. var radius:Number = diameter / 2;
  15. var matrix:Matrix = new Matrix();
  16.  
  17. var brushAlpha:BitmapData = new BitmapData(diameter, diameter, true, 0x00000000);
  18. drawRadial();
  19. brushAlpha.draw(brush);
  20.  
  21. var xp:Number = 0, yp:Number = 0, px:Number = 0, py:Number = 0;
  22. var dx:Number, dy:Number;
  23.  
  24. stage.addEventListener(MouseEvent.MOUSE_MOVE, onLoop);
  25. function onLoop(evt:Event):void {
  26.     xp = mouseX - radius;
  27.     yp = mouseY - radius;
  28.     dx = xp - px;
  29.     dy = yp - py;
  30.     canvas.copyPixels(canvas,
  31.                     new Rectangle(px, py, diameter, diameter),
  32.                     new Point(xp, yp), brushAlpha, new Point(0,0), true);
  33.     px = xp;
  34.     py = yp
  35. }
  36.  
  37. function drawRadial():void{
  38.     matrix.createGradientBox(diameter, diameter, 0, 0, 0);
  39.     with (brush.graphics){
  40.         beginGradientFill(GradientType.RADIAL, [0xFFFFFF, 0xFFFFFF], [1,0], [0, 255], matrix, SpreadMethod.PAD);
  41.         drawCircle(radius, radius, radius);
  42.     }
  43. }

This is a quick snippet I wrote while thinking about how to create a smudge tool using BitmapData... it isn't perfect, but it's a good first step. It still needs some linear interpolation and I may need to do some pixel pushing to prevent a strange alpha anomaly that causes the brush to get darker than expected....


Here is the swf...

Posted in BitmapData | Tagged , , | 1 Comment