Category Archives: 3D

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

Also posted in Graphics, Vector | 2 Comments

Isometric Cones (spikes)

Actionscript:
  1. [SWF(width = 600, height = 500, backgroundColor=0xFFFFFF)]
  2.  
  3. var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0xFFFFFF);
  4. addChild(new Bitmap(canvas));
  5.  
  6. var matrix:Matrix = new Matrix();
  7. var grid:Sprite =   new Sprite();
  8. grid.filters = [new DropShadowFilter(4, 0, 0, 0.05, 20, 10)];
  9. matrix.rotate(Math.PI / 4);
  10. matrix.scale(1, 0.6);
  11. matrix.translate(stage.stageWidth / 2, stage.stageHeight / 2 + 50);
  12. grid.transform.matrix = matrix;
  13.  
  14. var rowCol:int = 9;
  15. var spikeNum:Number = rowCol * rowCol;
  16. var diameter:Number = 30;
  17. var space:Number  = diameter + 10;
  18. var halfGridSize:Number  = rowCol * space / 2;
  19. var radius:Number;
  20. addEventListener(Event.ENTER_FRAME, onLoop);
  21. function onLoop(evt:Event):void {
  22.     radius  = diameter / 2;
  23.     grid.y -= 0.9;
  24.     grid.graphics.clear();
  25.     for (var i:Number = 0; i<spikeNum; i++){
  26.        var xp:Number = i % rowCol;
  27.        var yp:Number = int(i / rowCol);
  28.        drawSpike(xp * space - halfGridSize, yp * space - halfGridSize, (xp + yp) / 4, 0, -yp);
  29.     }
  30.     canvas.draw(grid, grid.transform.matrix);
  31.     diameter -= 0.5;
  32.     if (diameter <3){
  33.         removeEventListener(Event.ENTER_FRAME, onLoop);
  34.     }
  35. }
  36. function drawSpike(xp:Number, yp:Number, rot:Number = 0, xOff:Number=0, yOff:Number = 0):void{
  37.     matrix.createGradientBox(diameter, diameter, rot, xp - radius + yOff, yp - radius + xOff);
  38.     with (grid.graphics){
  39.         beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0x999999], [1,1], [0, 255], matrix, SpreadMethod.PAD);
  40.         drawCircle(xp, yp, radius);
  41.     }
  42. }

This snippet draws some isometric cones. Here are some images created by tweaking a few of the values:

Also posted in BitmapData, misc | Tagged , , | Leave a comment

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 BitmapData, Math, Vector, graphics algorithms, matrix, setPixel | Tagged , , | 3 Comments

Vectorpark Style Cylinder

Actionscript:
  1. const TWO_PI:Number = Math.PI * 2;
  2. const PI_HALF_PI:Number = Math.PI + Math.PI / 2;
  3. x = stage.stageWidth / 2;
  4. y = stage.stageHeight / 2;
  5. var runCylinder:Function = makeCylinder(0,0, 100, 300, 0xFF0000, 0xFFCC00);
  6. var dx:Number = 0;
  7. var dy:Number = 0;
  8. addEventListener(Event.ENTER_FRAME, onLoop);
  9. function onLoop(evt:Event):void {
  10.     dx += (mouseX / 50 - dx) / 4;
  11.     dy += (mouseY - dy) / 4;
  12.     runCylinder(dx, dy);
  13. }
  14. function makeCylinder(x:Number, y:Number, size:Number, length:Number, colA:uint, colB:uint):Function{
  15.     var s:Sprite = Sprite(addChild(new Sprite()));
  16.     s.x = x;
  17.     s.y = y;
  18.     var acol:uint = colB;
  19.     var bcol:uint = colB;
  20.     var halfLength:Number = length / 2;
  21.     var capA:Sprite = Sprite(s.addChild(new Sprite()));
  22.     var box:Sprite = Sprite(s.addChild(new Sprite()));
  23.     var w:Number = size * 2;
  24.     var h:Number = length;
  25.     with (box.graphics)  beginFill(colA), drawRect(-w/2, -h/2, w,h);
  26.     var capB:Sprite = Sprite(s.addChild(new Sprite()));
  27.     return function(theta:Number, rot:Number){
  28.         theta %= TWO_PI;
  29.         if (theta <0){
  30.             theta = TWO_PI - -theta;
  31.         }
  32.         var scale:Number = Math.cos(theta);
  33.         if (theta> 1.57){
  34.             acol = colA;
  35.             s.addChild(capB);
  36.             bcol = colB;
  37.         } else {
  38.             acol = colB;
  39.             bcol = colA;
  40.             s.addChild(capA);
  41.         }
  42.         if (theta> PI_HALF_PI){
  43.             acol = colB;
  44.             bcol = colA;
  45.             s.addChild(capA);
  46.         }
  47.        
  48.         var sin:Number = Math.sin(theta);
  49.         box.scaleY = sin;
  50.         capA.y = halfLength * sin;
  51.         capB.y = -capA.y;
  52.         with(capA.graphics) clear(), beginFill(acol), scaleYcircle(capA.graphics,size, scale);
  53.         with(capB.graphics) clear(), beginFill(bcol), scaleYcircle(capB.graphics,size, scale);
  54.         s.rotation = rot;
  55.     }
  56. }
  57. // original circle function by senocular (www.senocular.com) from here http://www.actionscript.org/forums/showthread.php3?s=&threadid=30328
  58. // circle that can be scaled on the y axis
  59. function scaleYcircle(g:Graphics, r:Number, s:Number = 1):void {
  60.     var c1:Number = r * (Math.SQRT2 - 1);
  61.     var c2:Number = r * Math.SQRT2 / 2;
  62.     var rs:Number = r * s, c1s:Number = c1 * s, c2s:Number = c2 * s;
  63.     var x_r:Number =  -r, y_r:Number = -rs, x_c2:Number =  -c2;
  64.     var y_c2:Number =  -c2s, x_c1:Number =  -c1, y_c1:Number =  -c1s
  65.     g.moveTo(r, 0), g.curveTo(r, c1s, c2, c2s);
  66.     g.curveTo(c1, rs, 0, rs), g.curveTo(x_c1,rs, x_c2, c2s);
  67.     g.curveTo(x_r, c1s, x_r, 0), g.curveTo(x_r,y_c1,x_c2,y_c2);
  68.     g.curveTo(x_c1,y_r,0,y_r), g.curveTo(c1,y_r,c2,y_c2);
  69.     g.curveTo(r,y_c1,r,0);
  70. }

This is similar to the last post I did.... inspired by some of the great stuff over at VectorPark.com... this snippet creates a 3D cylinder out of two circles and a box...

Also posted in Graphics | Tagged , , | Leave a comment