Category Archives: matrix

Quick Pixel Sphere

Actionscript:
  1. var pointNum:int = 20000;
  2. var radius:int = 150;
  3.  
  4. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
  5. addChild(new Bitmap(canvas));
  6. var verts:Vector.<Number>  = new Vector.<Number>();
  7. var pVerts:Vector.<Number> = new Vector.<Number>();
  8. var uv:Vector.<Number> = new Vector.<Number>();
  9.  
  10. for (var i:int = 0; i<pointNum; i+=3){
  11.     var xp:Number = Math.random() * 400 - 200;
  12.     var yp:Number = Math.random() * 400 - 200;
  13.     var zp:Number = Math.random() * 400 - 200;
  14.     var dist:Number = Math.sqrt(xp * xp + yp * yp + zp * zp);
  15.     // normalize and scale x,y,z
  16.     verts[i] = xp / dist * radius;
  17.     verts[i+1] = yp / dist * radius;
  18.     verts[i+2] = zp / dist * radius;
  19. }
  20.  
  21. var m:Matrix3D = new Matrix3D();
  22. var dx:Number = 0, dy:Number = 0;
  23. addEventListener(Event.ENTER_FRAME, onLoop);
  24. function onLoop(evt:Event):void {
  25.        m.identity();
  26.        dx += (mouseX - dx) / 4;
  27.        dy += (mouseY - dy) / 4;
  28.        m.appendRotation(dx, Vector3D.X_AXIS);
  29.        m.appendRotation(dy, Vector3D.Y_AXIS);
  30.        m.appendTranslation(200,200,0);
  31.        Utils3D.projectVectors(m, verts, pVerts, uv);
  32.        canvas.fillRect(canvas.rect, 0x000000);
  33.        for (var i:int = 0; i<pVerts.length; i+=2){
  34.          canvas.setPixel(pVerts[i], pVerts[i + 1], 0xFFFFFF);
  35.        }
  36. }

This snippet shows a quick way to randomly place a bunch of xyz coordinates on the surface of a sphere. I saw this trick in an OpenGL book a few years back - dug around my books but couldn't find it... If I find it I'll update this post.

The trick is achieved by normalizing the vector defined by each 3D coordinate...


Have a look at the swf...

Also posted in 3D, BitmapData, Math, setPixel | Tagged , , | 4 Comments

Another Matrix.transformPoint()

Actionscript:
  1. [SWF(width = 628, height=500)]
  2. var trans:Matrix = new Matrix();
  3. var pnt:Point = new Point();
  4. x = stage.stageWidth / 2;
  5. y = stage.stageHeight / 2;
  6. addEventListener(Event.ENTER_FRAME, onLoop);
  7. function onLoop(evt:Event):void {
  8.     graphics.clear();
  9.     graphics.lineStyle(10, 0x000000, 1, false, LineScaleMode.NORMAL, CapsStyle.SQUARE);
  10.     pnt.x = 0;
  11.     pnt.y = 0;
  12.     trans.identity();
  13.     trans.translate(15,15);
  14.     trans.rotate(mouseX/10 * Math.PI / 180);
  15.     graphics.moveTo(pnt.x, pnt.y);
  16.     for (var i:int = 0; i<12; i++){
  17.         pnt = trans.transformPoint(pnt);
  18.         graphics.lineTo(pnt.x, pnt.y);
  19.     }
  20. }

I was thinking about processing and OpenGL today... I always really enjoyed using matrix stuff, working with the matrix stack, using push() and pop() etc... Understanding how to use matrices is pretty important when your doing advanced graphics in actionscript. If you haven't messed with matrices, this snippet is a good place to start. It uses Matrix.transformPoint() to draw a series of connected lines that are controlled by the x location of the mouse. Back before flash 8, this kind of thing was usually done using trig or MovieClip nesting...

I posted another snippet on this topic awhile back.

Also posted in motion | 2 Comments

Utils3D.projectVectors() Lathe

Actionscript:
  1. [SWF(width = 500, height = 500, backgroundColor = 0x000000)]
  2. var halfWidth:Number = stage.stageWidth / 2;
  3. var halfHeight:Number = stage.stageHeight / 2;
  4. var loc:Vector.<Number>;
  5.  
  6. graphics.lineStyle(0, 0xFF0000);
  7. graphics.moveTo(halfWidth, 0);
  8. graphics.lineTo(halfWidth, stage.stageHeight);
  9. graphics.moveTo(0, halfHeight);
  10. graphics.lineTo(stage.stageWidth, halfHeight);
  11.  
  12. var line:Shape = Shape(addChild(new Shape()));
  13. line.x = halfWidth;
  14.  
  15. var idle:Function = function(){};
  16. var currentMode:Function = idle;
  17. stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
  18. stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
  19. addEventListener(Event.ENTER_FRAME, onLoop);
  20. function onDown(evt:MouseEvent):void{
  21.     if (contains(frame)){
  22.         removeChild(frame);
  23.         currentMode = idle;
  24.         line.graphics.clear();
  25.         return;
  26.     }
  27.     loc = new Vector.<Number>();
  28.     line.graphics.lineStyle(0,0xFFFFFF);
  29.     line.x = halfWidth
  30.     line.y = halfHeight;
  31.     line.graphics.moveTo(line.mouseX, line.mouseY);
  32.     currentMode = captureLocs;
  33.     canvas.fillRect(canvas.rect, 0x000000);
  34. }
  35. function onUp(evt:MouseEvent):void{
  36.     if (currentMode == idle) return;
  37.     setupLathe();
  38.     currentMode = showLathe;
  39. }
  40.  
  41. function onLoop(evt:Event):void{
  42.     currentMode();
  43. }
  44. function captureLocs():void{
  45.     loc.push(line.mouseX);
  46.     loc.push(line.mouseY);
  47.     loc.push(0);
  48.     line.graphics.lineTo(line.mouseX, line.mouseY);
  49. }
  50. /**
  51.  -- Lathe Stuff:
  52. */
  53. var canvas:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight,false, 0x000000);
  54. var frame:Bitmap = new Bitmap(canvas);
  55. var dx:Number=0;
  56. var dy:Number=0;
  57.  var matrix:Matrix3D = new Matrix3D();
  58. var pVerts:Vector.<Number>;
  59. var uvts:Vector.<Number>;
  60. function setupLathe():void{
  61.     addChild(frame);
  62.     pVerts =  new Vector.<Number>();
  63.     uvts = new Vector.<Number>();
  64.     var nVerts:Vector.<Number> = new Vector.<Number>();
  65.     var tVerts:Vector.<Number> = new Vector.<Number>();
  66.     matrix.identity();
  67.     var step:Number = 2;
  68.     for (var i:int = 0; i <360; i+=step){
  69.         matrix.appendRotation(step,Vector3D.Y_AXIS);
  70.         matrix.transformVectors(loc, tVerts);
  71.         nVerts = nVerts.concat(tVerts);
  72.     }
  73.     loc = nVerts.concat();
  74. }
  75. function showLathe():void{
  76.     dx += (mouseX - dx)/4;
  77.     dy += (mouseY - dy)/4;
  78.     matrix.identity();
  79.     matrix.appendRotation(dy,Vector3D.X_AXIS);
  80.     matrix.appendRotation(dx,Vector3D.Y_AXIS);
  81.     matrix.appendTranslation(halfWidth, halfHeight, 0);
  82.     Utils3D.projectVectors(matrix, loc, pVerts, uvts);
  83.     canvas.lock();
  84.     canvas.fillRect(canvas.rect, 0x000000);
  85.     var leng:int = pVerts.length;
  86.     for (var i:int = 0; i<leng; i+=2){
  87.         canvas.setPixel( pVerts[i], pVerts[i + 1], 0xFFFFFF);
  88.     }
  89.     canvas.unlock();
  90. }

This snippet allows you to create 3D lathe shapes by drawing a 2D line. This is done using Utils3D.projectVectors() and Matrix.transformVectors().

Have a look at the swf here...

Also posted in 3D, BitmapData, Math, Vector, graphics algorithms, setPixel | Tagged , , | 3 Comments

Distance Render

Actionscript:
  1. var verts:Vector.<Number> = new Vector.<Number>();
  2. var pVerts:Vector.<Number> = new Vector.<Number>();
  3. var uvts:Vector.<Number> = new Vector.<Number>();
  4.  
  5. var hs:Number = 2.3;
  6. var step:Number = 0.04;
  7.  
  8. var tVerts:Vector.<Number> = new Vector.<Number>();
  9. var rVerts:Vector.<Number> = new Vector.<Number>();
  10. var matrix:Matrix3D = new Matrix3D();
  11. matrix.identity();
  12. matrix.appendRotation(45,Vector3D.Y_AXIS);
  13. matrix.appendRotation(45,Vector3D.X_AXIS);
  14. var inc:int = 0;
  15. var i:Number, j:Number, k:Number;
  16. i = hs;
  17. while( i> -hs){
  18.     j = hs;
  19.     while(j> -hs){
  20.         k = hs;
  21.         while(k> -hs){
  22.             tVerts[inc] = -i;
  23.             inc++
  24.             tVerts[inc] = -j;
  25.             inc++
  26.             tVerts[inc] = -k;
  27.             inc++
  28.             k -= step;
  29.         }
  30.         j -= step;
  31.     }
  32.     i -= step;
  33. }
  34.  
  35. matrix.transformVectors(tVerts, rVerts);
  36.  
  37. var vinc:int = 0;
  38. inc = 0
  39. var R:Number = 1.5;
  40. var r:Number = .5;
  41. for (i= -hs; i<hs; i+=step){
  42.     for (j = -hs; j<hs; j+=step){
  43.         for (k = -hs; k<hs; k+=step){
  44.             var vx:Number = rVerts[inc] ;
  45.             inc++
  46.             var vy:Number = rVerts[inc]  ;
  47.             inc++
  48.             var vz:Number=  rVerts[inc] ;
  49.             inc++
  50.             var s:Number = Math.pow(vx  * vx  + vy * vy + vz * vz + R*R - r * r, 2) - 4 * (R * R)*(vx * vx + vy * vy);
  51.             if (s <0 && s> -.5){
  52.                 verts[vinc] = (i * 50);
  53.                 vinc++
  54.                 verts[vinc] = (j * 50);
  55.                 vinc++
  56.                 verts[vinc] = (k * 50);
  57.                 vinc++
  58.                   inc += int((hs - k) / step) * 3;
  59.                   k = hs;
  60.              }
  61.         }
  62.     }
  63. }
  64.  
  65. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
  66. addChild(new Bitmap(canvas));
  67. render();
  68. function render():void{
  69.     matrix.identity();
  70.     matrix.appendTranslation(200, 200, 0);
  71.     Utils3D.projectVectors(matrix, verts, pVerts, uvts);
  72.     canvas.lock();
  73.     canvas.fillRect(canvas.rect, 0x000000);
  74.     var inc:int = 2;
  75.     var c:int = 0;
  76.     var r:Rectangle = new Rectangle();
  77.     r.width = r.height = 2;
  78.     for (var i:int = 0; i<pVerts.length; i+=2){
  79.           r.x = pVerts[i];
  80.           r.y = pVerts[i + 1];
  81.           c = Math.max(0,100 - verts[inc]);
  82.           canvas.fillRect(r, c <<16 | c <<8 | c);
  83.           inc += 3;
  84.     }
  85.     canvas.unlock();
  86. }

This snippet uses some of the techniques from the last few posts to create a distance render - this renders the implicit equation for a torus.

Also posted in BitmapData, Math, Vector, color, graphics algorithms, pixel manipulation | Tagged , | Leave a comment