Category Archives: misc

Fake Light w/ UV & Quads

Actionscript:
  1. [SWF(width = 500, height=500, backgroundColor = 0x000000)]
  2. x = stage.stageWidth / 2;
  3. y = stage.stageHeight / 2;
  4. var quadNum:int = 2200;
  5. // standard Vectors for using drawTriangles
  6. var verts:Vector.<Number> = new Vector.<Number>();
  7. var pVerts:Vector.<Number>;
  8. var uvts:Vector.<Number> = new Vector.<Number>();
  9. var indices:Vector.<int> = new Vector.<int>();
  10. // needed for z-sorting
  11. var sortedIndices:Vector.<int>;
  12. var faces:Array = [];
  13. // we'll use this for tranforming points
  14. // and as the transformation matrix for our render
  15. var m:Matrix3D = new Matrix3D();
  16. // plot a quad
  17. var quad:Vector.<Number>;
  18. quad = Vector.<Number>([-10, -10, 0,
  19.                         10, -10, 0,
  20.                         -10, 10, 0,
  21.                         10, 10, 0]);
  22. // temp vect for any transformed quads
  23. var transQuad:Vector.<Number> = new Vector.<Number>();
  24. var i:int;
  25. var inc:int = 0;
  26. for (i = 0; i<quadNum; i++){
  27.     m.identity();
  28.     var s:Number = (int(Math.random()*50) == 1) ? 2 + Math.random()*2 : .1 + Math.random() * 2;
  29.     m.appendScale(s, s, 1);
  30.     m.appendRotation(90, Vector3D.Y_AXIS);
  31.     var mult:Number = 100 + Math.random()*200;
  32.     m.appendTranslation(mult, 0, 0);
  33.     m.appendRotation(Math.random()*360, Vector3D.X_AXIS);
  34.     m.appendRotation(Math.random()*360, Vector3D.Y_AXIS);
  35.     m.appendRotation(Math.random()*360, Vector3D.Z_AXIS);
  36.     m.transformVectors(quad, transQuad);
  37.     verts = verts.concat(transQuad);
  38.     faces.push(new Vector3D());
  39.     faces.push(new Vector3D());
  40.     var i4:int = i * 4;
  41.     indices.push(0 + i4, 1 + i4, 2 + i4,
  42.                  1 + i4, 3 + i4, 2 + i4);
  43.     mult /= 300;
  44.     uvts.push(mult,mult,0,
  45.               mult+.1,mult,0,
  46.               mult,mult - .1,0,
  47.               mult + .1,mult + .1,0);
  48. }
  49. sortedIndices = new Vector.<int>(indices.length, true);
  50. // create texture
  51. var tex:BitmapData = new BitmapData(400,400,false, 0x000000);
  52. var grad:Shape = new Shape();
  53. var mat:Matrix = new Matrix();
  54. mat.createGradientBox(400,400,0,0,0);
  55. with (grad.graphics){
  56.     beginGradientFill(GradientType.LINEAR, [0xFFFFFF,0x002244], [1, 1], [100, 255], mat);
  57.     drawRect(0,0,400,400);
  58. }
  59. tex.draw(grad);
  60. // create background
  61. mat.createGradientBox(1600,1200,0,-550, 0);
  62. with (grad.graphics){
  63.     beginGradientFill(GradientType.RADIAL, [0x000000, 0x001133], [1, 1], [0, 255], mat);
  64.     drawRect(0,0,500,500);
  65. }
  66. grad.x = -stage.stageWidth/2
  67. grad.y = -stage.stageHeight/2;
  68. addChild(grad);
  69. // triangles will be drawn to this
  70. var render:Shape = Shape(addChild(new Shape()));
  71. // fix all vector lengths
  72. verts.fixed = true, uvts.fixed = true, indices.fixed = true
  73. pVerts = new Vector.<Number>(verts.length/3 * 2, true);
  74. // we need these if we want perspective
  75. var persp:PerspectiveProjection = new PerspectiveProjection();
  76. persp.fieldOfView = 45;
  77. // projection matrix
  78. var proj:Matrix3D = persp.toMatrix3D();
  79. var dx:Number = 0, dy:Number = 0;
  80. addEventListener(Event.ENTER_FRAME, onLoop);
  81. function onLoop(evt:Event):void {
  82.     dx += (mouseX - dx) / 4;
  83.     dy += (mouseY - dy) / 4;
  84.     m.identity();
  85.     m.appendRotation(dy, Vector3D.X_AXIS);
  86.     m.appendRotation(dx, Vector3D.Y_AXIS);
  87.     m.appendTranslation(0,0,800);
  88.     m.append(proj);
  89.     Utils3D.projectVectors(m, verts, pVerts, uvts);
  90.     var face:Vector3D;
  91.     inc = 0;
  92.     for (var i:int = 0; i<indices.length; i+=3){
  93.         face = faces[inc];
  94.         face.x = indices[i];
  95.         face.y = indices[int(i + 1)];
  96.         face.z = indices[int(i + 2)];
  97.         var i3:int = i * 3;
  98.         face.w = (uvts[int(face.x*3 + 2)] + uvts[int(face.y*3 + 2)] + uvts[int(face.z*3 + 2)]) * 0.333333;
  99.         inc++;
  100.     }
  101.     faces.sortOn("w", Array.NUMERIC);
  102.     inc = 0;
  103.     for each (face in faces){
  104.         sortedIndices[inc++] = face.x;
  105.         sortedIndices[inc++] = face.y;
  106.         sortedIndices[inc++] = face.z;
  107.     }
  108.     render.graphics.clear();
  109.     render.graphics.beginBitmapFill(tex, null, false, false);
  110.     render.graphics.drawTriangles(pVerts, sortedIndices, uvts, TriangleCulling.NEGATIVE);
  111. }

Expanding again on the z-sorting demos from the last few days - this snippet uses UV coords and a gradient to create something that vaguely resembles a light. Unlike the previous demos, the 3D cluster in this snippet is made up of quads - requiring a slight adjustment to the depth calculation.


Have a look at the swf...

I also posted the code over at wonderfl.net...

Also posted in 3D, Graphics, Vector, matrix, sortOn | Tagged , , , | 2 Comments

More z-sorting

Actionscript:
  1. [SWF(width = 500, height=500, backgroundColor = 0x333333)]
  2. x = stage.stageWidth / 2;
  3. y = stage.stageHeight / 2;
  4.  
  5.  
  6. var polyNum:int = 3000;
  7. // standard Vectors for using drawTriangles
  8. var verts:Vector.<Number> = new Vector.<Number>();
  9. var pVerts:Vector.<Number>;
  10. var uvts:Vector.<Number> = new Vector.<Number>();
  11. var indices:Vector.<int> = new Vector.<int>();
  12. // needed for z-sorting
  13. var sortedIndices:Vector.<int>;
  14. var faces:Array = [];
  15.  
  16. // we'll use this for tranforming points
  17. // and as the transormation matrix for our render
  18. var m:Matrix3D = new Matrix3D();
  19.  
  20. // plot a poly
  21. var poly:Vector.<Number>;
  22. poly = Vector.<Number>([ 0, 0, 0,
  23.                         10, 0, 0,
  24.                         0,10, 0]);
  25.  
  26. // temp vect for any transformed polygons
  27. var transPoly:Vector.<Number> = new Vector.<Number>();
  28.  
  29. var i:int;
  30. var inc:int = 0;
  31. for (i = 0; i<polyNum; i++){
  32.     m.identity();
  33.     var s:Number = (int(Math.random()*50) == 1) ? 4 + Math.random()*2 : 1 + Math.random() * 2;
  34.     m.appendScale(s, s, 1);
  35.     m.appendRotation(Math.random()*360, Vector3D.X_AXIS);
  36.     m.appendRotation(Math.random()*360, Vector3D.Y_AXIS);
  37.     m.appendRotation(Math.random()*360, Vector3D.Z_AXIS);
  38.     m.appendTranslation(200,0,0);
  39.                          
  40.     m.appendRotation(Math.random()*360, Vector3D.X_AXIS);
  41.     m.appendRotation(Math.random()*360, Vector3D.Y_AXIS);
  42.     m.appendRotation(Math.random()*360, Vector3D.Z_AXIS);
  43.    
  44.     m.transformVectors(poly, transPoly);
  45.    
  46.     verts = verts.concat(transPoly);
  47.     faces.push(new Vector3D());
  48.     indices.push(inc++, inc++, inc++);
  49.     uvts.push(Math.random(), Math.random(), 0, Math.random(), Math.random(), 0, Math.random(), Math.random(), 0);
  50. }
  51.  
  52. sortedIndices = new Vector.<int>(indices.length, true);
  53.  
  54. // create texture
  55. var tex:BitmapData = new BitmapData(400,400,false, 0x000000);
  56. var grad:Shape = new Shape();
  57. var mat:Matrix = new Matrix();
  58. mat.createGradientBox(400,400,0,0,0);
  59. with (grad.graphics){
  60.     beginGradientFill(GradientType.LINEAR, [0x000000, 0xAA0000, 0xFFFF00], [1, 1, 1], [20, 200, 255], mat);
  61.     drawRect(0,0,400,400);
  62. }
  63. tex.draw(grad);
  64.  
  65. // create background
  66. mat.createGradientBox(1600,1000,0,-550, -100);
  67. with (grad.graphics){
  68.     beginGradientFill(GradientType.RADIAL, [0x333333, 0xffffff], [1, 1], [0, 255], mat);
  69.     drawRect(0,0,500,500);
  70. }
  71. grad.x = -stage.stageWidth/2
  72. grad.y = -stage.stageHeight/2;
  73. addChild(grad);
  74.  
  75. // triangles will be drawn to this
  76. var render:Shape = Shape(addChild(new Shape()));
  77.  
  78. // fix all vector lengths
  79. verts.fixed = true, uvts.fixed = true, indices.fixed = true
  80. pVerts = new Vector.<Number>(verts.length/3 * 2, true);
  81.  
  82. // we need these if we want perspective
  83. var persp:PerspectiveProjection = new PerspectiveProjection();
  84. persp.fieldOfView = 45;
  85. // projection matrix
  86. var proj:Matrix3D = persp.toMatrix3D();
  87.  
  88. var dx:Number = 0, dy:Number = 0;
  89. addEventListener(Event.ENTER_FRAME, onLoop);
  90. function onLoop(evt:Event):void {
  91.     dx += (mouseX - dx) / 4;
  92.     dy += (mouseY - dy) / 4;
  93.     m.identity();
  94.     m.appendRotation(dy, Vector3D.X_AXIS);
  95.     m.appendRotation(dx, Vector3D.Y_AXIS);
  96.     // push everything back so its not to close
  97.     m.appendTranslation(0,0,800);
  98.     // append the projection matrix at the end
  99.     m.append(proj);
  100.    
  101.     Utils3D.projectVectors(m, verts, pVerts, uvts);
  102.    
  103.     var face:Vector3D;
  104.     inc = 0;
  105.     for (var i:int = 0; i<indices.length; i+=3){
  106.         face = faces[inc];
  107.         face.x = indices[i];
  108.         // it may look odd, but casting to an int
  109.         // when doing operations inside array sytnax
  110.         // adds a big speed boost
  111.         face.y = indices[int(i + 1)];
  112.         face.z = indices[int(i + 2)];
  113.         var i3:int = i * 3;
  114.         // get the average z position (t value) and store it in the Vector3D w property
  115.         // depending on your model, you may not need to do an average of all 3 values
  116.         face.w = (uvts[int(i3 + 2)] + uvts[int(i3 + 5)] + uvts[int(i3 + 8)]) * 0.333333;
  117.         inc++;
  118.     }
  119.      
  120.     // sort on w, so far this beats all other sorting methods for speed,
  121.     // faster than Vector.sort(), faster than any custom sort method I could find
  122.     faces.sortOn("w", Array.NUMERIC);
  123.  
  124.     // re-order indices so that faces are drawn in the correct order (back to front);
  125.     inc = 0;
  126.     for each (face in faces){
  127.         sortedIndices[inc++] = face.x;
  128.         sortedIndices[inc++] = face.y;
  129.         sortedIndices[inc++] = face.z;
  130.     }
  131.    
  132.     render.graphics.clear();
  133.     render.graphics.beginBitmapFill(tex, null, false, false);
  134.     render.graphics.drawTriangles(pVerts, sortedIndices, uvts, TriangleCulling.NONE);
  135. }

This is a slightly more advanced version of the z-sorting demo from yesterday. Here 3000 polygons are randomly arranged in a sphere formation...


Have a look at the swf...

Also posted in 3D, Graphics, Vector, matrix | Tagged , , , , | 6 Comments

globalToLocal() in 3D

Actionscript:
  1. [SWF(frameRate=60, backgroundColor=0x000000, width=500, height=500)]
  2. stage.quality = "medium";
  3. var frame:Sprite = Sprite(addChild(new Sprite()));
  4. with (frame.graphics) beginFill(0xCCCCCC), drawRect(-200, -200, 400, 400), endFill();
  5. frame.x = stage.stageWidth / 2;
  6. frame.y = stage.stageHeight / 2;
  7. frame.z = 100;
  8.  
  9. var canvas:Shape = Shape(frame.addChild(new Shape()));
  10. var msk:Shape = Shape(frame.addChild(new Shape()));
  11. with (msk.graphics) beginFill(0x00FF00), drawRect(-200, -200, 400, 400), endFill();
  12. canvas.mask = msk
  13.  
  14. var txt:TextField = TextField(addChild(new TextField()));
  15. txt.defaultTextFormat = new TextFormat("_sans", 12);
  16. txt.x = txt.y = 10;
  17. txt.textColor = 0xFFFFFF, txt.autoSize="left", txt.text = "Draw on the 3D plane...";
  18.  
  19. stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
  20. stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
  21. function onDown(evt:MouseEvent):void{
  22.     canvas.graphics.lineStyle(4, 0x000000);
  23.     var pnt:Point = frame.globalToLocal(new Point(mouseX, mouseY));
  24.     canvas.graphics.moveTo(pnt.x, pnt.y);
  25.     addEventListener(Event.ENTER_FRAME, onDraw);
  26. }
  27. function onUp(evt:MouseEvent):void{
  28.     removeEventListener(Event.ENTER_FRAME, onDraw);
  29. }
  30.  
  31. var t:Number = 0;
  32. addEventListener(Event.ENTER_FRAME, onLoop);
  33. function onLoop(evt:Event):void {
  34.     frame.rotationY = 35 * Math.sin(t);
  35.     frame.rotationX = 35 * Math.cos(t);
  36.     t+=0.02;
  37. }
  38.  
  39. function onDraw(evt:Event):void {
  40.         var pnt:Point = frame.globalToLocal(new Point(mouseX, mouseY));
  41.     canvas.graphics.lineTo(pnt.x, pnt.y);
  42. }

This demo shows that globalToLocal() works with 3D - saving us the trouble of doing some extra math if we want to draw on 3D display objects...

Have a look at the swf....


Was made aware of this trick by watching a video that kevinSuttle sent me via twitter. The video is an interview with Chris Nuuja (one of the flash player engineers).

Also posted in 3D, DisplayObject, Graphics, motion | Tagged , , | 3 Comments

BitmapData Static

Actionscript:
  1. var canvas:BitmapData = new BitmapData(500,500,false, 0x000000);
  2. addChild(new Bitmap(canvas));
  3.  
  4. var pix:Vector.<uint> = new Vector.<uint>(canvas.width * canvas.height, true);
  5.  
  6. addEventListener(Event.ENTER_FRAME, onLoop);
  7. function onLoop(evt:Event):void {
  8.     canvas.lock();
  9.     var i:int = pix.length;
  10.     while(--i> -1){
  11.         var c:uint = uint(Math.random() * 255);
  12.         pix[i] = c <<16 | c <<8 | c;
  13.     }
  14.     canvas.setVector(canvas.rect, pix);
  15.     canvas.unlock();
  16. }

This is an easy way to fill a BitmapData Object up with a bunch of TV-style static....

This post is meant to serve as filler while I work to get a good solid SIMPLE fp10, drawing api z-sorting example going... There seem to be 3 main ways of doing z-sorting all of which don't seem right to me for some reason... they all work... but I have a gut feeling there is a faster way... The winner so far (unexpectedly) is using Array.sortOn

Also posted in BitmapData, Vector | Tagged , , | 6 Comments