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

This entry was posted in 3D, Graphics, Vector, matrix, misc, sortOn and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

2 Comments

  1. J
    Posted September 2, 2009 at 4:58 am | Permalink

    Waouhou ! Really nice effect

  2. Posted September 2, 2009 at 1:23 pm | Permalink

    Thanks J

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*