notice: Flash editor updated! Join the development! Thanks to MiniBuilder


embed

FAVORITE BY
:
3d3d
:
:
3DParticle軽い!
:
Cool!
:
:
:
3Dパーティクル花火火花Matrix3D花火きれい!逆さまだとシュール…
:
3DParticle軽い!
:
:
:
nice
:
particle 3d firework
:
:
:
Particleと物理シミュレーション
:
:
3DMatrix3DVector火花が3Dに飛び散る マウスによって角度が変わる
:
:
beautiful!
:
sparks
:
:
:
:
:
:
3D étincelles
:
no3thclassfirework
:
:
:
Particleすげえ
:
きれいだなぁ
:
:
:
that's amazing!!xD
:
:
:
wow
:
:
particlesThis is friggin awesome!
:
:
花火
:
particles3dparticles 3d
:
:
:
:
Volcanowow this is great!
:
すごいパーティクル
:
:
hypnotic(lol)Particles3DWow, beautiful
:
fireworkblurparticlewonderfull!!
:
3D花火 3D
:
:
花火だー
:
particlesparticles firework
:
ライブラリなしでここまでできるとは。
:
:
:
fireworkwow, thats neat, very polished effect
:
particle
:
Particleparticlephysics3dPS2デモっぽいパーティクルエフェクト
:
:
3d
:
:
:
:
:
:
:
76人目!
:
Dragon
:
:
スゴ
:
:
3D
:
:
:
花火!ファイアー
:
awesome !
:
Feuerwerk
:
ファイヤー
:
ワンダフルでPS的なパーティクルの実験
:
Nice fx
:
火花
:
wonderfl
:
はなび
:
すごい!!
:
お、おお・・!!!
:
すご
:
うひょー
:
すごい
:
すげ!!!! 花火3D
:
すげー
:
スパーク!!
:
sparks
:
超すごい
:
particleスパーク!
:
3Dphysicsおぉ美しい.
:
すげー
:
スパーク
:
fire
:
噴火っぽい
:
花火!すごい!
FORKED
  1. // forked from k0rin's PS2 Firework (Particles and Motion blur)
  2. package {
  3.     import flash.display.*;
  4.     import flash.events.*;
  5.     import flash.filters.*;
  6.     import flash.geom.*;
  7.     import flash.text.*;
  8.     import flash.utils.*;
  9.     [SWF(width="465", height="465", frameRate="40")]
  10.     public class Firework extends Sprite
  11.     {
  12.         // 火花
  13.         private var position:Vector.<Number> = new Vector.<Number>();
  14.         private var velocity:Vector.<Number> = new Vector.<Number>();
  15.         private var diameters:Vector.<Number> = new Vector.<Number>();
  16.         private var sparkNumber:Number = 0;
  17.         
  18.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  19.         private var uvts:Vector.<Number> = new Vector.<Number>();
  20.         
  21.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  22.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  23.         private const SPARK_COLOR:uint = 0x664020;
  24.         
  25.         private const GRAVITY:Number = 0.02;
  26.         private const AIR_RESISTANCE:Number = 0.999;
  27.         
  28.         // 1フレームに放出する火花の数
  29.         private const EMIT_SPARK_NUMBER:int = 3;
  30.         
  31.         // 照り返し
  32.         private var reflectionBitmapData:BitmapData;
  33.         private const REFLECTION_COLOR:uint = 0xFF1800;
  34.         private const REFLECTION_RADIUS:Number = 16;
  35.         
  36.         // フレームバッファ
  37.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  38.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  39.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  40.         
  41.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  42.         private var projectionMatrix:Matrix3D = new Matrix3D();
  43.         
  44.         private var viewRotationY:Number = 0;
  45.         private var viewRotationX:Number = 25;
  46.         
  47.         private const CENTER_X:Number = stage.stageWidth / 2;
  48.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  49.         
  50.         private var stats:TextField = new TextField();
  51.         
  52.         public function Firework()
  53.         {
  54.             addChild(new Bitmap(displayBuffer));
  55.             stats.x = 5;
  56.             stats.y = 5;
  57.             stats.autoSize = TextFieldAutoSize.LEFT;
  58.             stats.textColor = 0xFFFFFF;
  59.             addChild(stats);
  60.             
  61.             var shape:Shape = new Shape();
  62.             var g:Graphics = shape.graphics;
  63.             
  64.             // 火花のプリレンダリング
  65.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  66.             sparkBitmapDatas.push(bitmapData);
  67.             sparkBitmapDataRectangles.push(bitmapData.rect);
  68.             
  69.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  70.                 bitmapData = new BitmapData(diameter, diameter, true0);
  71.                 
  72.                 g.clear();
  73.                 g.beginFill(SPARK_COLOR);
  74.                 var radius:Number = diameter / 2;
  75.                 g.drawCircle(radius, radius, radius);
  76.                 g.endFill();
  77.                 bitmapData.draw(shape);
  78.                 
  79.                 sparkBitmapDatas.push(bitmapData);
  80.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  81.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  82.             }
  83.             
  84.             // 照り返しのプリレンダリング
  85.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  86.             g.clear();
  87.             var matrix:Matrix = new Matrix();
  88.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  89.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  90.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  91.             g.endFill();
  92.             reflectionBitmapData.draw(shape);
  93.             
  94.             createFireworkModel();
  95.             
  96.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  97. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  98. //                emitSpark();
  99. //            });
  100.         }
  101.         
  102.         private function enterFrameHandler(e:Event):void
  103.         {
  104.             displayBuffer.fillRect(displayBuffer.rect, 0);
  105.             
  106.             setupProjectionMatrix();
  107.             
  108.             var startTime:uint = getTimer();
  109.             renderFloor();
  110.             var floorRenderingTime:uint = getTimer() - startTime;
  111.             
  112.             startTime = getTimer();
  113.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  114.                 const FACTOR:Number = 0.06;
  115.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  116.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  117.                 
  118.                 setupProjectionMatrix();
  119.                 
  120.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  121.                     emitSpark();
  122.                 }
  123.                 updateSparks();
  124.                 renderSparks();
  125.             }
  126.             var sparksRenderingTime:uint = getTimer() - startTime;
  127.             
  128.             stats.text = 
  129.                 "Number of Sparks : " + sparkNumber + "\n" + 
  130.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  131.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  132.         }
  133.         
  134.         private function setupProjectionMatrix():void
  135.         {
  136.             perspective.fieldOfView = 60;
  137.             
  138.             projectionMatrix.identity();
  139.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  140.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  141.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  142.             projectionMatrix.append(perspective.toMatrix3D());
  143.             
  144.             correctMatrix3DMultiplyBug(projectionMatrix);
  145.         }
  146.         
  147.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  148.         {
  149.             // see http://bugs.adobe.com/jira/browse/FP-670
  150.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  151.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  152.             m1.append(m2);
  153.             if (m1.rawData[15] == 20) {
  154.                 // バグ持ち!
  155.                 var rawData:Vector.<Number> = matrix.rawData;
  156.                 rawData[15] /= 20;
  157.                 matrix.rawData = rawData;
  158.             }
  159.         }
  160.         
  161.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  162.         {
  163.             position.push(x, y, z);
  164.             velocity.push(vx, vy, vz);
  165.             diameters.push(diameter);
  166.             sparkNumber++;
  167.         }
  168.         
  169.         private function emitSpark():void
  170.         {
  171.             var azimuth:Number = Math.random() * 2 * Math.PI;
  172.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  173.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  174.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  175.             
  176.             var speed:Number = Math.random() * 2.3 + 0.7;
  177.             vx *= speed;
  178.             vy *= speed;
  179.             vz *= speed;
  180.             
  181.             var diameter:Number = 3 + Math.random() * 3;
  182.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  183.         }
  184.         
  185.         private function updateSparks():void
  186.         {
  187.             for (var i:int = 0; i < sparkNumber; ) {
  188.                 var xIndex:int = i * 3;
  189.                 var yIndex:int = xIndex + 1;
  190.                 var zIndex:int = xIndex + 2;
  191.                 
  192.                 velocity[yIndex] += GRAVITY;
  193.                 
  194.                 velocity[xIndex] *= AIR_RESISTANCE;
  195.                 velocity[yIndex] *= AIR_RESISTANCE;
  196.                 velocity[zIndex] *= AIR_RESISTANCE;
  197.                 
  198.                 if (position[yIndex] + velocity[yIndex] > 0) {
  199.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  200.                     
  201.                     position[xIndex] += velocity[xIndex];
  202.                     position[yIndex] += velocity[yIndex];
  203.                     position[zIndex] += velocity[zIndex];
  204.                     
  205.                     // 小さい火花に分割
  206.                     const DIAMETER_MIN:Number = 2;
  207.                     if (diameters[i] > DIAMETER_MIN) {
  208.                         var diameterLimit:Number = diameters[i];
  209.                         
  210.                         while (1) {
  211.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  212.                             diameterLimit -= diameter;
  213.                             if (diameterLimit < 0) {
  214.                                 break;
  215.                             }
  216.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  217.                             var r:Number = Math.random() * 2;
  218.                             
  219.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  220.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  221.                                 velocity[yIndex], 
  222.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  223.                                 diameter);
  224.                         }
  225.                     }
  226.                     
  227.                     // spliceは重い!
  228. //                    position.splice(xIndex, 3);
  229. //                    velocity.splice(xIndex, 3); 
  230. //                    diameters.splice(i, 1);
  231.                     position[xIndex] = position[sparkNumber * 3 - 3];
  232.                     position[yIndex] = position[sparkNumber * 3 - 2];
  233.                     position[zIndex] = position[sparkNumber * 3 - 1];
  234.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  235.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  236.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  237.                     
  238.                     diameters[i] = diameters[sparkNumber - 1];
  239.                     
  240.                     position.pop();
  241.                     position.pop();
  242.                     position.pop();
  243.                     velocity.pop();
  244.                     velocity.pop();
  245.                     velocity.pop();
  246.                     
  247.                     diameters.pop();
  248.                     
  249.                     sparkNumber--;
  250.                     continue;
  251.                 }
  252.                 position[xIndex] += velocity[xIndex];
  253.                 position[yIndex] += velocity[yIndex];
  254.                 position[zIndex] += velocity[zIndex];
  255.                 
  256.                 i++;
  257.             }
  258.         }
  259.         
  260.         private function renderSparks():void
  261.         {
  262.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  263.             
  264.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  265.             
  266.             // ループ外に追い出したら30%以上高速化
  267.             var p:Point = new Point();
  268.             var focalLength:Number = perspective.focalLength;
  269.             
  270.             for (var i:int = 0; i < sparkNumber; i++) {
  271.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  272.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  273.                 // (i * 2) => (i << 1)で10%ほど高速化
  274.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  275.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  276.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  277.             }
  278.             
  279.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  280.         }
  281.         
  282.         private const FLOOR_SIZE:Number = 300;
  283.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  284.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  285.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  286.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  287.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  288.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  289.              
  290.              FLOOR_HALFSIZE, 0,               0
  291.             -FLOOR_HALFSIZE, 0,               0
  292.                           00,  FLOOR_HALFSIZE, 
  293.                           00, -FLOOR_HALFSIZE, 
  294.         ]);
  295.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  296.         
  297.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  298.         private var floorIndices:Vector.<int> = Vector.<int>([
  299.             012,  230
  300.         ]);
  301.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  302.             100,  000,  010,  110,  
  303.             000,  000,  000,  000
  304.         ]);
  305.         
  306.         private const TEXTURE_SIZE:int = 150;
  307.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  308.         
  309.         private const WIREFRAME_COLOR:uint = 0x555566;
  310.         
  311.         private var sprite:Sprite = new Sprite();
  312.         
  313.         private function renderFloor():void
  314.         {
  315.             // 照り返しを描画する閾値
  316.             const THRESHOLD_Y:Number = 50;
  317.             
  318.             var matrix:Matrix = new Matrix();
  319.             var colorTransform:ColorTransform = new ColorTransform();
  320.             
  321.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  322.             
  323.             for (var i:int = 0; i < sparkNumber; i++) {
  324.                 var yIndex:int = i * 3 + 1;
  325.                 
  326.                 if (position[yIndex] > -THRESHOLD_Y) {
  327.                     var xIndex:int = i * 3;
  328.                     var zIndex:int = i * 3 + 2;
  329.                     
  330.                     matrix.identity();
  331.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  332.                     matrix.scale(scale, scale);
  333.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  334.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  335.                     
  336.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  337.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  338.                 }
  339.             }
  340.             
  341.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  342.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  343.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  344.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  345.             }
  346.             
  347.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  348.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  349.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  350.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  351.             }
  352.             
  353.             var g:Graphics = sprite.graphics;
  354.             g.clear();
  355.             g.beginBitmapFill(floorTexture);
  356.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  357.             g.endFill();
  358.             displayBuffer.draw(sprite);
  359.             
  360.             g.clear();
  361.             g.lineStyle(1, WIREFRAME_COLOR);
  362.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  363.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  364.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  365.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  366.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  367.             
  368.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  369.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  370.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  371.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  372.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  373.             
  374.             g.clear();
  375.             g.beginFill(FIREWORK_COLOR);
  376.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  377.             g.endFill();
  378.             displayBuffer.draw(sprite);
  379.         }
  380.         
  381.         private const FIREWORK_RADIUS:Number = 8;
  382.         private const FIREWORK_HEIGHT:Number = 40;
  383.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  384.         
  385.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  386.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  387.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  389.         
  390.         private function createFireworkModel():void
  391.         {
  392.             const SEGMENT:int = 8;
  393.             for (var i:int = 0; i < SEGMENT; i++) {
  394.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  395.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  396.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  397.                 fireworkVertices.push(x, 0, z);
  398.                 
  399.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  400.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  401.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  402.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  403.                 fireworkIndices.push(i2, i0, i1);
  404.                 fireworkIndices.push(i1, i3, i2);
  405.             }
  406.         }
  407.     }
  408. }
noswf
  1. // forked from k0rin's PS2 Firework (Particles and Motion blur)
  2. package {
  3.     import flash.display.*;
  4.     import flash.events.*;
  5.     import flash.filters.*;
  6.     import flash.geom.*;
  7.     import flash.text.*;
  8.     import flash.utils.*;
  9.     [SWF(width="465", height="465", frameRate="40")]
  10.     public class Firework extends Sprite
  11.     {
  12.         // 火花
  13.         private var position:Vector.<Number> = new Vector.<Number>();
  14.         private var velocity:Vector.<Number> = new Vector.<Number>();
  15.         private var diameters:Vector.<Number> = new Vector.<Number>();
  16.         private var sparkNumber:Number = 0;
  17.         
  18.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  19.         private var uvts:Vector.<Number> = new Vector.<Number>();
  20.         
  21.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  22.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  23.         private const SPARK_COLOR:uint = 0x664020;
  24.         
  25.         private const GRAVITY:Number = 0.02;
  26.         private const AIR_RESISTANCE:Number = 0.999;
  27.         
  28.         // 1フレームに放出する火花の数
  29.         private const EMIT_SPARK_NUMBER:int = 3;
  30.         
  31.         // 照り返し
  32.         private var reflectionBitmapData:BitmapData;
  33.         private const REFLECTION_COLOR:uint = 0xFF1800;
  34.         private const REFLECTION_RADIUS:Number = 16;
  35.         
  36.         // フレームバッファ
  37.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  38.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  39.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  40.         
  41.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  42.         private var projectionMatrix:Matrix3D = new Matrix3D();
  43.         
  44.         private var viewRotationY:Number = 0;
  45.         private var viewRotationX:Number = 25;
  46.         
  47.         private const CENTER_X:Number = stage.stageWidth / 2;
  48.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  49.         
  50.         private var stats:TextField = new TextField();
  51.         
  52.         public function Firework()
  53.         {
  54.             addChild(new Bitmap(displayBuffer));
  55.             stats.x = 5;
  56.             stats.y = 5;
  57.             stats.autoSize = TextFieldAutoSize.LEFT;
  58.             stats.textColor = 0xFFFFFF;
  59.             addChild(stats);
  60.             
  61.             var shape:Shape = new Shape();
  62.             var g:Graphics = shape.graphics;
  63.             
  64.             // 火花のプリレンダリング
  65.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  66.             sparkBitmapDatas.push(bitmapData);
  67.             sparkBitmapDataRectangles.push(bitmapData.rect);
  68.             
  69.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  70.                 bitmapData = new BitmapData(diameter, diameter, true0);
  71.                 
  72.                 g.clear();
  73.                 g.beginFill(SPARK_COLOR);
  74.                 var radius:Number = diameter / 2;
  75.                 g.drawCircle(radius, radius, radius);
  76.                 g.endFill();
  77.                 bitmapData.draw(shape);
  78.                 
  79.                 sparkBitmapDatas.push(bitmapData);
  80.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  81.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  82.             }
  83.             
  84.             // 照り返しのプリレンダリング
  85.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  86.             g.clear();
  87.             var matrix:Matrix = new Matrix();
  88.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  89.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  90.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  91.             g.endFill();
  92.             reflectionBitmapData.draw(shape);
  93.             
  94.             createFireworkModel();
  95.             
  96.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  97. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  98. //                emitSpark();
  99. //            });
  100.         }
  101.         
  102.         private function enterFrameHandler(e:Event):void
  103.         {
  104.             displayBuffer.fillRect(displayBuffer.rect, 0);
  105.             
  106.             setupProjectionMatrix();
  107.             
  108.             var startTime:uint = getTimer();
  109.             renderFloor();
  110.             var floorRenderingTime:uint = getTimer() - startTime;
  111.             
  112.             startTime = getTimer();
  113.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  114.                 const FACTOR:Number = 0.06;
  115.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  116.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  117.                 
  118.                 setupProjectionMatrix();
  119.                 
  120.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  121.                     emitSpark();
  122.                 }
  123.                 updateSparks();
  124.                 renderSparks();
  125.             }
  126.             var sparksRenderingTime:uint = getTimer() - startTime;
  127.             
  128.             stats.text = 
  129.                 "Number of Sparks : " + sparkNumber + "\n" + 
  130.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  131.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  132.         }
  133.         
  134.         private function setupProjectionMatrix():void
  135.         {
  136.             perspective.fieldOfView = 60;
  137.             
  138.             projectionMatrix.identity();
  139.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  140.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  141.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  142.             projectionMatrix.append(perspective.toMatrix3D());
  143.             
  144.             correctMatrix3DMultiplyBug(projectionMatrix);
  145.         }
  146.         
  147.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  148.         {
  149.             // see http://bugs.adobe.com/jira/browse/FP-670
  150.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  151.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  152.             m1.append(m2);
  153.             if (m1.rawData[15] == 20) {
  154.                 // バグ持ち!
  155.                 var rawData:Vector.<Number> = matrix.rawData;
  156.                 rawData[15] /= 20;
  157.                 matrix.rawData = rawData;
  158.             }
  159.         }
  160.         
  161.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  162.         {
  163.             position.push(x, y, z);
  164.             velocity.push(vx, vy, vz);
  165.             diameters.push(diameter);
  166.             sparkNumber++;
  167.         }
  168.         
  169.         private function emitSpark():void
  170.         {
  171.             var azimuth:Number = Math.random() * 2 * Math.PI;
  172.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  173.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  174.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  175.             
  176.             var speed:Number = Math.random() * 2.3 + 0.7;
  177.             vx *= speed;
  178.             vy *= speed;
  179.             vz *= speed;
  180.             
  181.             var diameter:Number = 3 + Math.random() * 3;
  182.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  183.         }
  184.         
  185.         private function updateSparks():void
  186.         {
  187.             for (var i:int = 0; i < sparkNumber; ) {
  188.                 var xIndex:int = i * 3;
  189.                 var yIndex:int = xIndex + 1;
  190.                 var zIndex:int = xIndex + 2;
  191.                 
  192.                 velocity[yIndex] += GRAVITY;
  193.                 
  194.                 velocity[xIndex] *= AIR_RESISTANCE;
  195.                 velocity[yIndex] *= AIR_RESISTANCE;
  196.                 velocity[zIndex] *= AIR_RESISTANCE;
  197.                 
  198.                 if (position[yIndex] + velocity[yIndex] > 0) {
  199.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  200.                     
  201.                     position[xIndex] += velocity[xIndex];
  202.                     position[yIndex] += velocity[yIndex];
  203.                     position[zIndex] += velocity[zIndex];
  204.                     
  205.                     // 小さい火花に分割
  206.                     const DIAMETER_MIN:Number = 2;
  207.                     if (diameters[i] > DIAMETER_MIN) {
  208.                         var diameterLimit:Number = diameters[i];
  209.                         
  210.                         while (1) {
  211.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  212.                             diameterLimit -= diameter;
  213.                             if (diameterLimit < 0) {
  214.                                 break;
  215.                             }
  216.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  217.                             var r:Number = Math.random() * 2;
  218.                             
  219.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  220.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  221.                                 velocity[yIndex], 
  222.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  223.                                 diameter);
  224.                         }
  225.                     }
  226.                     
  227.                     // spliceは重い!
  228. //                    position.splice(xIndex, 3);
  229. //                    velocity.splice(xIndex, 3); 
  230. //                    diameters.splice(i, 1);
  231.                     position[xIndex] = position[sparkNumber * 3 - 3];
  232.                     position[yIndex] = position[sparkNumber * 3 - 2];
  233.                     position[zIndex] = position[sparkNumber * 3 - 1];
  234.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  235.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  236.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  237.                     
  238.                     diameters[i] = diameters[sparkNumber - 1];
  239.                     
  240.                     position.pop();
  241.                     position.pop();
  242.                     position.pop();
  243.                     velocity.pop();
  244.                     velocity.pop();
  245.                     velocity.pop();
  246.                     
  247.                     diameters.pop();
  248.                     
  249.                     sparkNumber--;
  250.                     continue;
  251.                 }
  252.                 position[xIndex] += velocity[xIndex];
  253.                 position[yIndex] += velocity[yIndex];
  254.                 position[zIndex] += velocity[zIndex];
  255.                 
  256.                 i++;
  257.             }
  258.         }
  259.         
  260.         private function renderSparks():void
  261.         {
  262.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  263.             
  264.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  265.             
  266.             // ループ外に追い出したら30%以上高速化
  267.             var p:Point = new Point();
  268.             var focalLength:Number = perspective.focalLength;
  269.             
  270.             for (var i:int = 0; i < sparkNumber; i++) {
  271.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  272.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  273.                 // (i * 2) => (i << 1)で10%ほど高速化
  274.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  275.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  276.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  277.             }
  278.             
  279.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  280.         }
  281.         
  282.         private const FLOOR_SIZE:Number = 300;
  283.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  284.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  285.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  286.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  287.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  288.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  289.              
  290.              FLOOR_HALFSIZE, 0,               0
  291.             -FLOOR_HALFSIZE, 0,               0
  292.                           00,  FLOOR_HALFSIZE, 
  293.                           00, -FLOOR_HALFSIZE, 
  294.         ]);
  295.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  296.         
  297.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  298.         private var floorIndices:Vector.<int> = Vector.<int>([
  299.             012,  230
  300.         ]);
  301.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  302.             100,  000,  010,  110,  
  303.             000,  000,  000,  000
  304.         ]);
  305.         
  306.         private const TEXTURE_SIZE:int = 150;
  307.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  308.         
  309.         private const WIREFRAME_COLOR:uint = 0x555566;
  310.         
  311.         private var sprite:Sprite = new Sprite();
  312.         
  313.         private function renderFloor():void
  314.         {
  315.             // 照り返しを描画する閾値
  316.             const THRESHOLD_Y:Number = 50;
  317.             
  318.             var matrix:Matrix = new Matrix();
  319.             var colorTransform:ColorTransform = new ColorTransform();
  320.             
  321.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  322.             
  323.             for (var i:int = 0; i < sparkNumber; i++) {
  324.                 var yIndex:int = i * 3 + 1;
  325.                 
  326.                 if (position[yIndex] > -THRESHOLD_Y) {
  327.                     var xIndex:int = i * 3;
  328.                     var zIndex:int = i * 3 + 2;
  329.                     
  330.                     matrix.identity();
  331.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  332.                     matrix.scale(scale, scale);
  333.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  334.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  335.                     
  336.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  337.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  338.                 }
  339.             }
  340.             
  341.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  342.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  343.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  344.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  345.             }
  346.             
  347.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  348.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  349.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  350.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  351.             }
  352.             
  353.             var g:Graphics = sprite.graphics;
  354.             g.clear();
  355.             g.beginBitmapFill(floorTexture);
  356.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  357.             g.endFill();
  358.             displayBuffer.draw(sprite);
  359.             
  360.             g.clear();
  361.             g.lineStyle(1, WIREFRAME_COLOR);
  362.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  363.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  364.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  365.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  366.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  367.             
  368.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  369.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  370.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  371.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  372.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  373.             
  374.             g.clear();
  375.             g.beginFill(FIREWORK_COLOR);
  376.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  377.             g.endFill();
  378.             displayBuffer.draw(sprite);
  379.         }
  380.         
  381.         private const FIREWORK_RADIUS:Number = 8;
  382.         private const FIREWORK_HEIGHT:Number = 40;
  383.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  384.         
  385.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  386.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  387.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  389.         
  390.         private function createFireworkModel():void
  391.         {
  392.             const SEGMENT:int = 8;
  393.             for (var i:int = 0; i < SEGMENT; i++) {
  394.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  395.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  396.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  397.                 fireworkVertices.push(x, 0, z);
  398.                 
  399.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  400.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  401.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  402.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  403.                 fireworkIndices.push(i2, i0, i1);
  404.                 fireworkIndices.push(i1, i3, i2);
  405.             }
  406.         }
  407.     }
  408. }
noswf
  1. // forked from k0rin's PS2 Firework (Particles and Motion blur)
  2. package {
  3.     import flash.display.*;
  4.     import flash.events.*;
  5.     import flash.filters.*;
  6.     import flash.geom.*;
  7.     import flash.text.*;
  8.     import flash.utils.*;
  9.     [SWF(width="465", height="465", frameRate="40")]
  10.     public class Firework extends Sprite
  11.     {
  12.         // 火花
  13.         private var position:Vector.<Number> = new Vector.<Number>();
  14.         private var velocity:Vector.<Number> = new Vector.<Number>();
  15.         private var diameters:Vector.<Number> = new Vector.<Number>();
  16.         private var sparkNumber:Number = 0;
  17.         
  18.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  19.         private var uvts:Vector.<Number> = new Vector.<Number>();
  20.         
  21.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  22.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  23.         private const SPARK_COLOR:uint = 0x004066;
  24.         
  25.         private const GRAVITY:Number = 0.02;
  26.         private const AIR_RESISTANCE:Number = 0.999;
  27.         
  28.         // 1フレームに放出する火花の数
  29.         private const EMIT_SPARK_NUMBER:int = 3;
  30.         
  31.         // 照り返し
  32.         private var reflectionBitmapData:BitmapData;
  33.         private const REFLECTION_COLOR:uint = 0xFF1800;
  34.         private const REFLECTION_RADIUS:Number = 16;
  35.         
  36.         // フレームバッファ
  37.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  38.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  39.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  40.         
  41.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  42.         private var projectionMatrix:Matrix3D = new Matrix3D();
  43.         
  44.         private var viewRotationY:Number = 0;
  45.         private var viewRotationX:Number = 25;
  46.         
  47.         private const CENTER_X:Number = stage.stageWidth / 2;
  48.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  49.         
  50.         private var stats:TextField = new TextField();
  51.         
  52.         public function Firework()
  53.         {
  54.             addChild(new Bitmap(displayBuffer));
  55.             stats.x = 5;
  56.             stats.y = 5;
  57.             stats.autoSize = TextFieldAutoSize.LEFT;
  58.             stats.textColor = 0xFFFFFF;
  59.             addChild(stats);
  60.             
  61.             var shape:Shape = new Shape();
  62.             var g:Graphics = shape.graphics;
  63.             
  64.             // 火花のプリレンダリング
  65.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  66.             sparkBitmapDatas.push(bitmapData);
  67.             sparkBitmapDataRectangles.push(bitmapData.rect);
  68.             
  69.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  70.                 bitmapData = new BitmapData(diameter, diameter, true0);
  71.                 
  72.                 g.clear();
  73.                 g.beginFill(SPARK_COLOR);
  74.                 var radius:Number = diameter / 2;
  75.                 g.drawCircle(radius, radius, radius);
  76.                 g.endFill();
  77.                 bitmapData.draw(shape);
  78.                 
  79.                 sparkBitmapDatas.push(bitmapData);
  80.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  81.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  82.             }
  83.             
  84.             // 照り返しのプリレンダリング
  85.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  86.             g.clear();
  87.             var matrix:Matrix = new Matrix();
  88.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  89.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  90.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  91.             g.endFill();
  92.             reflectionBitmapData.draw(shape);
  93.             
  94.             createFireworkModel();
  95.             
  96.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  97. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  98. //                emitSpark();
  99. //            });
  100.         }
  101.         
  102.         private function enterFrameHandler(e:Event):void
  103.         {
  104.             displayBuffer.fillRect(displayBuffer.rect, 0);
  105.             
  106.             setupProjectionMatrix();
  107.             
  108.             var startTime:uint = getTimer();
  109.             renderFloor();
  110.             var floorRenderingTime:uint = getTimer() - startTime;
  111.             
  112.             startTime = getTimer();
  113.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  114.                 const FACTOR:Number = 0.06;
  115.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  116.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  117.                 
  118.                 setupProjectionMatrix();
  119.                 
  120.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  121.                     emitSpark();
  122.                 }
  123.                 updateSparks();
  124.                 renderSparks();
  125.             }
  126.             var sparksRenderingTime:uint = getTimer() - startTime;
  127.             
  128.             stats.text = 
  129.                 "Number of Sparks : " + sparkNumber + "\n" + 
  130.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  131.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  132.         }
  133.         
  134.         private function setupProjectionMatrix():void
  135.         {
  136.             perspective.fieldOfView = 60;
  137.             
  138.             projectionMatrix.identity();
  139.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  140.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  141.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  142.             projectionMatrix.append(perspective.toMatrix3D());
  143.             
  144.             correctMatrix3DMultiplyBug(projectionMatrix);
  145.         }
  146.         
  147.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  148.         {
  149.             // see http://bugs.adobe.com/jira/browse/FP-670
  150.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  151.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  152.             m1.append(m2);
  153.             if (m1.rawData[15] == 20) {
  154.                 // バグ持ち!
  155.                 var rawData:Vector.<Number> = matrix.rawData;
  156.                 rawData[15] /= 20;
  157.                 matrix.rawData = rawData;
  158.             }
  159.         }
  160.         
  161.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  162.         {
  163.             position.push(x, y, z);
  164.             velocity.push(vx, vy, vz);
  165.             diameters.push(diameter);
  166.             sparkNumber++;
  167.         }
  168.         
  169.         private function emitSpark():void
  170.         {
  171.             var azimuth:Number = Math.random() * 2 * Math.PI;
  172.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  173.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  174.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  175.             
  176.             var speed:Number = Math.random() * 2.3 + 0.7;
  177.             vx *= speed;
  178.             vy *= speed;
  179.             vz *= speed;
  180.             
  181.             var diameter:Number = 3 + Math.random() * 3;
  182.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  183.         }
  184.         
  185.         private function updateSparks():void
  186.         {
  187.             for (var i:int = 0; i < sparkNumber; ) {
  188.                 var xIndex:int = i * 3;
  189.                 var yIndex:int = xIndex + 1;
  190.                 var zIndex:int = xIndex + 2;
  191.                 
  192.                 velocity[yIndex] += GRAVITY;
  193.                 
  194.                 velocity[xIndex] *= AIR_RESISTANCE;
  195.                 velocity[yIndex] *= AIR_RESISTANCE;
  196.                 velocity[zIndex] *= AIR_RESISTANCE;
  197.                 
  198.                 if (position[yIndex] + velocity[yIndex] > 0) {
  199.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  200.                     
  201.                     position[xIndex] += velocity[xIndex];
  202.                     position[yIndex] += velocity[yIndex];
  203.                     position[zIndex] += velocity[zIndex];
  204.                     
  205.                     // 小さい火花に分割
  206.                     const DIAMETER_MIN:Number = 2;
  207.                     if (diameters[i] > DIAMETER_MIN) {
  208.                         var diameterLimit:Number = diameters[i];
  209.                         
  210.                         while (1) {
  211.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  212.                             diameterLimit -= diameter;
  213.                             if (diameterLimit < 0) {
  214.                                 break;
  215.                             }
  216.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  217.                             var r:Number = Math.random() * 2;
  218.                             
  219.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  220.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  221.                                 velocity[yIndex], 
  222.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  223.                                 diameter);
  224.                         }
  225.                     }
  226.                     
  227.                     // spliceは重い!
  228. //                    position.splice(xIndex, 3);
  229. //                    velocity.splice(xIndex, 3); 
  230. //                    diameters.splice(i, 1);
  231.                     position[xIndex] = position[sparkNumber * 3 - 3];
  232.                     position[yIndex] = position[sparkNumber * 3 - 2];
  233.                     position[zIndex] = position[sparkNumber * 3 - 1];
  234.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  235.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  236.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  237.                     
  238.                     diameters[i] = diameters[sparkNumber - 1];
  239.                     
  240.                     position.pop();
  241.                     position.pop();
  242.                     position.pop();
  243.                     velocity.pop();
  244.                     velocity.pop();
  245.                     velocity.pop();
  246.                     
  247.                     diameters.pop();
  248.                     
  249.                     sparkNumber--;
  250.                     continue;
  251.                 }
  252.                 position[xIndex] += velocity[xIndex];
  253.                 position[yIndex] += velocity[yIndex];
  254.                 position[zIndex] += velocity[zIndex];
  255.                 
  256.                 i++;
  257.             }
  258.         }
  259.         
  260.         private function renderSparks():void
  261.         {
  262.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  263.             
  264.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  265.             
  266.             // ループ外に追い出したら30%以上高速化
  267.             var p:Point = new Point();
  268.             var focalLength:Number = perspective.focalLength;
  269.             
  270.             for (var i:int = 0; i < sparkNumber; i++) {
  271.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  272.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  273.                 // (i * 2) => (i << 1)で10%ほど高速化
  274.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  275.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  276.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  277.             }
  278.             
  279.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  280.         }
  281.         
  282.         private const FLOOR_SIZE:Number = 300;
  283.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  284.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  285.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  286.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  287.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  288.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  289.              
  290.              FLOOR_HALFSIZE, 0,               0
  291.             -FLOOR_HALFSIZE, 0,               0
  292.                           00,  FLOOR_HALFSIZE, 
  293.                           00, -FLOOR_HALFSIZE, 
  294.         ]);
  295.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  296.         
  297.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  298.         private var floorIndices:Vector.<int> = Vector.<int>([
  299.             012,  230
  300.         ]);
  301.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  302.             100,  000,  010,  110,  
  303.             000,  000,  000,  000
  304.         ]);
  305.         
  306.         private const TEXTURE_SIZE:int = 150;
  307.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  308.         
  309.         private const WIREFRAME_COLOR:uint = 0x555566;
  310.         
  311.         private var sprite:Sprite = new Sprite();
  312.         
  313.         private function renderFloor():void
  314.         {
  315.             // 照り返しを描画する閾値
  316.             const THRESHOLD_Y:Number = 50;
  317.             
  318.             var matrix:Matrix = new Matrix();
  319.             var colorTransform:ColorTransform = new ColorTransform();
  320.             
  321.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  322.             
  323.             for (var i:int = 0; i < sparkNumber; i++) {
  324.                 var yIndex:int = i * 3 + 1;
  325.                 
  326.                 if (position[yIndex] > -THRESHOLD_Y) {
  327.                     var xIndex:int = i * 3;
  328.                     var zIndex:int = i * 3 + 2;
  329.                     
  330.                     matrix.identity();
  331.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  332.                     matrix.scale(scale, scale);
  333.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  334.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  335.                     
  336.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  337.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  338.                 }
  339.             }
  340.             
  341.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  342.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  343.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  344.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  345.             }
  346.             
  347.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  348.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  349.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  350.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  351.             }
  352.             
  353.             var g:Graphics = sprite.graphics;
  354.             g.clear();
  355.             g.beginBitmapFill(floorTexture);
  356.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  357.             g.endFill();
  358.             displayBuffer.draw(sprite);
  359.             
  360.             g.clear();
  361.             g.lineStyle(1, WIREFRAME_COLOR);
  362.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  363.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  364.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  365.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  366.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  367.             
  368.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  369.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  370.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  371.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  372.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  373.             
  374.             g.clear();
  375.             g.beginFill(FIREWORK_COLOR);
  376.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  377.             g.endFill();
  378.             displayBuffer.draw(sprite);
  379.         }
  380.         
  381.         private const FIREWORK_RADIUS:Number = 8;
  382.         private const FIREWORK_HEIGHT:Number = 40;
  383.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  384.         
  385.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  386.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  387.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  389.         
  390.         private function createFireworkModel():void
  391.         {
  392.             const SEGMENT:int = 8;
  393.             for (var i:int = 0; i < SEGMENT; i++) {
  394.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  395.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  396.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  397.                 fireworkVertices.push(x, 0, z);
  398.                 
  399.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  400.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  401.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  402.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  403.                 fireworkIndices.push(i2, i0, i1);
  404.                 fireworkIndices.push(i1, i3, i2);
  405.             }
  406.         }
  407.     }
  408. }
noswf
  1. // forked from k0rin's PS2 Firework (Particles and Motion blur)
  2. package {
  3.     import flash.display.*;
  4.     import flash.events.*;
  5.     import flash.filters.*;
  6.     import flash.geom.*;
  7.     import flash.text.*;
  8.     import flash.utils.*;
  9.     [SWF(width="465", height="465", frameRate="40")]
  10.     public class Firework extends Sprite
  11.     {
  12.         // 火花
  13.         private var position:Vector.<Number> = new Vector.<Number>();
  14.         private var velocity:Vector.<Number> = new Vector.<Number>();
  15.         private var diameters:Vector.<Number> = new Vector.<Number>();
  16.         private var sparkNumber:Number = 0;
  17.         
  18.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  19.         private var uvts:Vector.<Number> = new Vector.<Number>();
  20.         
  21.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  22.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  23.         private const SPARK_COLOR:uint = 0x664020;
  24.         
  25.         private const GRAVITY:Number = 0.02;
  26.         private const AIR_RESISTANCE:Number = 0.999;
  27.         
  28.         // 1フレームに放出する火花の数
  29.         private const EMIT_SPARK_NUMBER:int = 3;
  30.         
  31.         // 照り返し
  32.         private var reflectionBitmapData:BitmapData;
  33.         private const REFLECTION_COLOR:uint = 0xFF1800;
  34.         private const REFLECTION_RADIUS:Number = 16;
  35.         
  36.         // フレームバッファ
  37.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  38.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  39.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  40.         
  41.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  42.         private var projectionMatrix:Matrix3D = new Matrix3D();
  43.         
  44.         private var viewRotationY:Number = 0;
  45.         private var viewRotationX:Number = 25;
  46.         
  47.         private const CENTER_X:Number = stage.stageWidth / 2;
  48.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  49.         
  50.         private var stats:TextField = new TextField();
  51.         
  52.         public function Firework()
  53.         {
  54.             addChild(new Bitmap(displayBuffer));
  55.             stats.x = 5;
  56.             stats.y = 5;
  57.             stats.autoSize = TextFieldAutoSize.LEFT;
  58.             stats.textColor = 0xFFFFFF;
  59.             addChild(stats);
  60.             
  61.             var shape:Shape = new Shape();
  62.             var g:Graphics = shape.graphics;
  63.             
  64.             // 火花のプリレンダリング
  65.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  66.             sparkBitmapDatas.push(bitmapData);
  67.             sparkBitmapDataRectangles.push(bitmapData.rect);
  68.             
  69.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  70.                 bitmapData = new BitmapData(diameter, diameter, true0);
  71.                 
  72.                 g.clear();
  73.                 g.beginFill(SPARK_COLOR);
  74.                 var radius:Number = diameter / 2;
  75.                 g.drawCircle(radius, radius, radius);
  76.                 g.endFill();
  77.                 bitmapData.draw(shape);
  78.                 
  79.                 sparkBitmapDatas.push(bitmapData);
  80.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  81.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  82.             }
  83.             
  84.             // 照り返しのプリレンダリング
  85.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  86.             g.clear();
  87.             var matrix:Matrix = new Matrix();
  88.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  89.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  90.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  91.             g.endFill();
  92.             reflectionBitmapData.draw(shape);
  93.             
  94.             createFireworkModel();
  95.             
  96.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  97. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  98. //                emitSpark();
  99. //            });
  100.         }
  101.         
  102.         private function enterFrameHandler(e:Event):void
  103.         {
  104.             displayBuffer.fillRect(displayBuffer.rect, 0);
  105.             
  106.             setupProjectionMatrix();
  107.             
  108.             var startTime:uint = getTimer();
  109.             renderFloor();
  110.             var floorRenderingTime:uint = getTimer() - startTime;
  111.             
  112.             startTime = getTimer();
  113.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  114.                 const FACTOR:Number = 0.06;
  115.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  116.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  117.                 
  118.                 setupProjectionMatrix();
  119.                 
  120.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  121.                     emitSpark();
  122.                 }
  123.                 updateSparks();
  124.                 renderSparks();
  125.             }
  126.             var sparksRenderingTime:uint = getTimer() - startTime;
  127.             
  128.             stats.text = 
  129.                 "Number of Sparks : " + sparkNumber + "\n" + 
  130.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  131.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  132.         }
  133.         
  134.         private function setupProjectionMatrix():void
  135.         {
  136.             perspective.fieldOfView = 60;
  137.             
  138.             projectionMatrix.identity();
  139.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  140.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  141.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  142.             projectionMatrix.append(perspective.toMatrix3D());
  143.             
  144.             correctMatrix3DMultiplyBug(projectionMatrix);
  145.         }
  146.         
  147.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  148.         {
  149.             // see http://bugs.adobe.com/jira/browse/FP-670
  150.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  151.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  152.             m1.append(m2);
  153.             if (m1.rawData[15] == 20) {
  154.                 // バグ持ち!
  155.                 var rawData:Vector.<Number> = matrix.rawData;
  156.                 rawData[15] /= 20;
  157.                 matrix.rawData = rawData;
  158.             }
  159.         }
  160.         
  161.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  162.         {
  163.             position.push(x, y, z);
  164.             velocity.push(vx, vy, vz);
  165.             diameters.push(diameter);
  166.             sparkNumber++;
  167.         }
  168.         
  169.         private function emitSpark():void
  170.         {
  171.             var azimuth:Number = Math.random() * 2 * Math.PI;
  172.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  173.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  174.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  175.             
  176.             var speed:Number = Math.random() * 2.3 + 0.7;
  177.             vx *= speed;
  178.             vy *= speed;
  179.             vz *= speed;
  180.             
  181.             var diameter:Number = 3 + Math.random() * 3;
  182.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  183.         }
  184.         
  185.         private function updateSparks():void
  186.         {
  187.             for (var i:int = 0; i < sparkNumber; ) {
  188.                 var xIndex:int = i * 3;
  189.                 var yIndex:int = xIndex + 1;
  190.                 var zIndex:int = xIndex + 2;
  191.                 
  192.                 velocity[yIndex] += GRAVITY;
  193.                 
  194.                 velocity[xIndex] *= AIR_RESISTANCE;
  195.                 velocity[yIndex] *= AIR_RESISTANCE;
  196.                 velocity[zIndex] *= AIR_RESISTANCE;
  197.                 
  198.                 if (position[yIndex] + velocity[yIndex] > 0) {
  199.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  200.                     
  201.                     position[xIndex] += velocity[xIndex];
  202.                     position[yIndex] += velocity[yIndex];
  203.                     position[zIndex] += velocity[zIndex];
  204.                     
  205.                     // 小さい火花に分割
  206.                     const DIAMETER_MIN:Number = 2;
  207.                     if (diameters[i] > DIAMETER_MIN) {
  208.                         var diameterLimit:Number = diameters[i];
  209.                         
  210.                         while (1) {
  211.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  212.                             diameterLimit -= diameter;
  213.                             if (diameterLimit < 0) {
  214.                                 break;
  215.                             }
  216.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  217.                             var r:Number = Math.random() * 2;
  218.                             
  219.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  220.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  221.                                 velocity[yIndex], 
  222.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  223.                                 diameter);
  224.                         }
  225.                     }
  226.                     
  227.                     // spliceは重い!
  228. //                    position.splice(xIndex, 3);
  229. //                    velocity.splice(xIndex, 3); 
  230. //                    diameters.splice(i, 1);
  231.                     position[xIndex] = position[sparkNumber * 3 - 3];
  232.                     position[yIndex] = position[sparkNumber * 3 - 2];
  233.                     position[zIndex] = position[sparkNumber * 3 - 1];
  234.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  235.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  236.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  237.                     
  238.                     diameters[i] = diameters[sparkNumber - 1];
  239.                     
  240.                     position.pop();
  241.                     position.pop();
  242.                     position.pop();
  243.                     velocity.pop();
  244.                     velocity.pop();
  245.                     velocity.pop();
  246.                     
  247.                     diameters.pop();
  248.                     
  249.                     sparkNumber--;
  250.                     continue;
  251.                 }
  252.                 position[xIndex] += velocity[xIndex];
  253.                 position[yIndex] += velocity[yIndex];
  254.                 position[zIndex] += velocity[zIndex];
  255.                 
  256.                 i++;
  257.             }
  258.         }
  259.         
  260.         private function renderSparks():void
  261.         {
  262.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  263.             
  264.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  265.             
  266.             // ループ外に追い出したら30%以上高速化
  267.             var p:Point = new Point();
  268.             var focalLength:Number = perspective.focalLength;
  269.             
  270.             for (var i:int = 0; i < sparkNumber; i++) {
  271.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  272.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  273.                 // (i * 2) => (i << 1)で10%ほど高速化
  274.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  275.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  276.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  277.             }
  278.             
  279.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  280.         }
  281.         
  282.         private const FLOOR_SIZE:Number = 300;
  283.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  284.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  285.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  286.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  287.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  288.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  289.              
  290.              FLOOR_HALFSIZE, 0,               0
  291.             -FLOOR_HALFSIZE, 0,               0
  292.                           00,  FLOOR_HALFSIZE, 
  293.                           00, -FLOOR_HALFSIZE, 
  294.         ]);
  295.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  296.         
  297.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  298.         private var floorIndices:Vector.<int> = Vector.<int>([
  299.             012,  230
  300.         ]);
  301.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  302.             100,  000,  010,  110,  
  303.             000,  000,  000,  000
  304.         ]);
  305.         
  306.         private const TEXTURE_SIZE:int = 150;
  307.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  308.         
  309.         private const WIREFRAME_COLOR:uint = 0x555566;
  310.         
  311.         private var sprite:Sprite = new Sprite();
  312.         
  313.         private function renderFloor():void
  314.         {
  315.             // 照り返しを描画する閾値
  316.             const THRESHOLD_Y:Number = 50;
  317.             
  318.             var matrix:Matrix = new Matrix();
  319.             var colorTransform:ColorTransform = new ColorTransform();
  320.             
  321.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  322.             
  323.             for (var i:int = 0; i < sparkNumber; i++) {
  324.                 var yIndex:int = i * 3 + 1;
  325.                 
  326.                 if (position[yIndex] > -THRESHOLD_Y) {
  327.                     var xIndex:int = i * 3;
  328.                     var zIndex:int = i * 3 + 2;
  329.                     
  330.                     matrix.identity();
  331.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  332.                     matrix.scale(scale, scale);
  333.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  334.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  335.                     
  336.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  337.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  338.                 }
  339.             }
  340.             
  341.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  342.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  343.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  344.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  345.             }
  346.             
  347.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  348.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  349.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  350.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  351.             }
  352.             
  353.             var g:Graphics = sprite.graphics;
  354.             g.clear();
  355.             g.beginBitmapFill(floorTexture);
  356.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  357.             g.endFill();
  358.             displayBuffer.draw(sprite);
  359.             
  360.             g.clear();
  361.             g.lineStyle(1, WIREFRAME_COLOR);
  362.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  363.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  364.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  365.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  366.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  367.             
  368.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  369.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  370.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  371.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  372.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  373.             
  374.             g.clear();
  375.             g.beginFill(FIREWORK_COLOR);
  376.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  377.             g.endFill();
  378.             displayBuffer.draw(sprite);
  379.         }
  380.         
  381.         private const FIREWORK_RADIUS:Number = 8;
  382.         private const FIREWORK_HEIGHT:Number = 40;
  383.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  384.         
  385.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  386.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  387.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  389.         
  390.         private function createFireworkModel():void
  391.         {
  392.             const SEGMENT:int = 8;
  393.             for (var i:int = 0; i < SEGMENT; i++) {
  394.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  395.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  396.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  397.                 fireworkVertices.push(x, 0, z);
  398.                 
  399.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  400.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  401.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  402.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  403.                 fireworkIndices.push(i2, i0, i1);
  404.                 fireworkIndices.push(i1, i3, i2);
  405.             }
  406.         }
  407.     }
  408. }
noswf
  1. // forked from k0rin's PS2 Firework (Particles and Motion blur)
  2. package {
  3.     import flash.display.*;
  4.     import flash.events.*;
  5.     import flash.filters.*;
  6.     import flash.geom.*;
  7.     import flash.text.*;
  8.     import flash.utils.*;
  9.     [SWF(width="465", height="465", frameRate="40")]
  10.     public class Firework extends Sprite
  11.     {
  12.         // 火花
  13.         private var position:Vector.<Number> = new Vector.<Number>();
  14.         private var velocity:Vector.<Number> = new Vector.<Number>();
  15.         private var diameters:Vector.<Number> = new Vector.<Number>();
  16.         private var sparkNumber:Number = 0;
  17.         
  18.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  19.         private var uvts:Vector.<Number> = new Vector.<Number>();
  20.         
  21.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  22.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  23.         private const SPARK_COLOR:uint = 0x664020;
  24.         
  25.         private const GRAVITY:Number = 0.02;
  26.         private const AIR_RESISTANCE:Number = 0.999;
  27.         
  28.         // 1フレームに放出する火花の数
  29.         private const EMIT_SPARK_NUMBER:int = 3;
  30.         
  31.         // 照り返し
  32.         private var reflectionBitmapData:BitmapData;
  33.         private const REFLECTION_COLOR:uint = 0xFF1800;
  34.         private const REFLECTION_RADIUS:Number = 16;
  35.         
  36.         // フレームバッファ
  37.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  38.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  39.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  40.         
  41.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  42.         private var projectionMatrix:Matrix3D = new Matrix3D();
  43.         
  44.         private var viewRotationY:Number = 0;
  45.         private var viewRotationX:Number = 25;
  46.         
  47.         private const CENTER_X:Number = stage.stageWidth / 2;
  48.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  49.         
  50.         private var stats:TextField = new TextField();
  51.         
  52.         public function Firework()
  53.         {
  54.             addChild(new Bitmap(displayBuffer));
  55.             stats.x = 5;
  56.             stats.y = 5;
  57.             stats.autoSize = TextFieldAutoSize.LEFT;
  58.             stats.textColor = 0xFFFFFF;
  59.             addChild(stats);
  60.             
  61.             var shape:Shape = new Shape();
  62.             var g:Graphics = shape.graphics;
  63.             
  64.             // 火花のプリレンダリング
  65.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  66.             sparkBitmapDatas.push(bitmapData);
  67.             sparkBitmapDataRectangles.push(bitmapData.rect);
  68.             
  69.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  70.                 bitmapData = new BitmapData(diameter, diameter, true0);
  71.                 
  72.                 g.clear();
  73.                 g.beginFill(SPARK_COLOR);
  74.                 var radius:Number = diameter / 2;
  75.                 g.drawCircle(radius, radius, radius);
  76.                 g.endFill();
  77.                 bitmapData.draw(shape);
  78.                 
  79.                 sparkBitmapDatas.push(bitmapData);
  80.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  81.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  82.             }
  83.             
  84.             // 照り返しのプリレンダリング
  85.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  86.             g.clear();
  87.             var matrix:Matrix = new Matrix();
  88.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  89.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  90.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  91.             g.endFill();
  92.             reflectionBitmapData.draw(shape);
  93.             
  94.             createFireworkModel();
  95.             
  96.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  97. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  98. //                emitSpark();
  99. //            });
  100.         }
  101.         
  102.         private function enterFrameHandler(e:Event):void
  103.         {
  104.             displayBuffer.fillRect(displayBuffer.rect, 0);
  105.             
  106.             setupProjectionMatrix();
  107.             
  108.             var startTime:uint = getTimer();
  109.             renderFloor();
  110.             var floorRenderingTime:uint = getTimer() - startTime;
  111.             
  112.             startTime = getTimer();
  113.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  114.                 const FACTOR:Number = 0.06;
  115.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  116.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  117.                 
  118.                 setupProjectionMatrix();
  119.                 
  120.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  121.                     emitSpark();
  122.                 }
  123.                 updateSparks();
  124.                 renderSparks();
  125.             }
  126.             var sparksRenderingTime:uint = getTimer() - startTime;
  127.             
  128.             stats.text = 
  129.                 "Number of Sparks : " + sparkNumber + "\n" + 
  130.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  131.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  132.         }
  133.         
  134.         private function setupProjectionMatrix():void
  135.         {
  136.             perspective.fieldOfView = 60;
  137.             
  138.             projectionMatrix.identity();
  139.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  140.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  141.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  142.             projectionMatrix.append(perspective.toMatrix3D());
  143.             
  144.             correctMatrix3DMultiplyBug(projectionMatrix);
  145.         }
  146.         
  147.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  148.         {
  149.             // see http://bugs.adobe.com/jira/browse/FP-670
  150.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  151.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  152.             m1.append(m2);
  153.             if (m1.rawData[15] == 20) {
  154.                 // バグ持ち!
  155.                 var rawData:Vector.<Number> = matrix.rawData;
  156.                 rawData[15] /= 20;
  157.                 matrix.rawData = rawData;
  158.             }
  159.         }
  160.         
  161.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  162.         {
  163.             position.push(x, y, z);
  164.             velocity.push(vx, vy, vz);
  165.             diameters.push(diameter);
  166.             sparkNumber++;
  167.         }
  168.         
  169.         private function emitSpark():void
  170.         {
  171.             var azimuth:Number = Math.random() * 2 * Math.PI;
  172.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  173.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  174.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  175.             
  176.             var speed:Number = Math.random() * 2.3 + 0.7;
  177.             vx *= speed;
  178.             vy *= speed;
  179.             vz *= speed;
  180.             
  181.             var diameter:Number = 3 + Math.random() * 3;
  182.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  183.         }
  184.         
  185.         private function updateSparks():void
  186.         {
  187.             for (var i:int = 0; i < sparkNumber; ) {
  188.                 var xIndex:int = i * 3;
  189.                 var yIndex:int = xIndex + 1;
  190.                 var zIndex:int = xIndex + 2;
  191.                 
  192.                 velocity[yIndex] += GRAVITY;
  193.                 
  194.                 velocity[xIndex] *= AIR_RESISTANCE;
  195.                 velocity[yIndex] *= AIR_RESISTANCE;
  196.                 velocity[zIndex] *= AIR_RESISTANCE;
  197.                 
  198.                 if (position[yIndex] + velocity[yIndex] > 0) {
  199.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  200.                     
  201.                     position[xIndex] += velocity[xIndex];
  202.                     position[yIndex] += velocity[yIndex];
  203.                     position[zIndex] += velocity[zIndex];
  204.                     
  205.                     // 小さい火花に分割
  206.                     const DIAMETER_MIN:Number = 2;
  207.                     if (diameters[i] > DIAMETER_MIN) {
  208.                         var diameterLimit:Number = diameters[i];
  209.                         
  210.                         while (1) {
  211.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  212.                             diameterLimit -= diameter;
  213.                             if (diameterLimit < 0) {
  214.                                 break;
  215.                             }
  216.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  217.                             var r:Number = Math.random() * 2;
  218.                             
  219.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  220.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  221.                                 velocity[yIndex], 
  222.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  223.                                 diameter);
  224.                         }
  225.                     }
  226.                     
  227.                     // spliceは重い!
  228. //                    position.splice(xIndex, 3);
  229. //                    velocity.splice(xIndex, 3); 
  230. //                    diameters.splice(i, 1);
  231.                     position[xIndex] = position[sparkNumber * 3 - 3];
  232.                     position[yIndex] = position[sparkNumber * 3 - 2];
  233.                     position[zIndex] = position[sparkNumber * 3 - 1];
  234.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  235.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  236.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  237.                     
  238.                     diameters[i] = diameters[sparkNumber - 1];
  239.                     
  240.                     position.pop();
  241.                     position.pop();
  242.                     position.pop();
  243.                     velocity.pop();
  244.                     velocity.pop();
  245.                     velocity.pop();
  246.                     
  247.                     diameters.pop();
  248.                     
  249.                     sparkNumber--;
  250.                     continue;
  251.                 }
  252.                 position[xIndex] += velocity[xIndex];
  253.                 position[yIndex] += velocity[yIndex];
  254.                 position[zIndex] += velocity[zIndex];
  255.                 
  256.                 i++;
  257.             }
  258.         }
  259.         
  260.         private function renderSparks():void
  261.         {
  262.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  263.             
  264.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  265.             
  266.             // ループ外に追い出したら30%以上高速化
  267.             var p:Point = new Point();
  268.             var focalLength:Number = perspective.focalLength;
  269.             
  270.             for (var i:int = 0; i < sparkNumber; i++) {
  271.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  272.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  273.                 // (i * 2) => (i << 1)で10%ほど高速化
  274.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  275.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  276.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  277.             }
  278.             
  279.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  280.         }
  281.         
  282.         private const FLOOR_SIZE:Number = 300;
  283.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  284.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  285.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  286.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  287.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  288.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  289.              
  290.              FLOOR_HALFSIZE, 0,               0
  291.             -FLOOR_HALFSIZE, 0,               0
  292.                           00,  FLOOR_HALFSIZE, 
  293.                           00, -FLOOR_HALFSIZE, 
  294.         ]);
  295.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  296.         
  297.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  298.         private var floorIndices:Vector.<int> = Vector.<int>([
  299.             012,  230
  300.         ]);
  301.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  302.             100,  000,  010,  110,  
  303.             000,  000,  000,  000
  304.         ]);
  305.         
  306.         private const TEXTURE_SIZE:int = 150;
  307.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  308.         
  309.         private const WIREFRAME_COLOR:uint = 0x555566;
  310.         
  311.         private var sprite:Sprite = new Sprite();
  312.         
  313.         private function renderFloor():void
  314.         {
  315.             // 照り返しを描画する閾値
  316.             const THRESHOLD_Y:Number = 50;
  317.             
  318.             var matrix:Matrix = new Matrix();
  319.             var colorTransform:ColorTransform = new ColorTransform();
  320.             
  321.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  322.             
  323.             for (var i:int = 0; i < sparkNumber; i++) {
  324.                 var yIndex:int = i * 3 + 1;
  325.                 
  326.                 if (position[yIndex] > -THRESHOLD_Y) {
  327.                     var xIndex:int = i * 3;
  328.                     var zIndex:int = i * 3 + 2;
  329.                     
  330.                     matrix.identity();
  331.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  332.                     matrix.scale(scale, scale);
  333.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  334.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  335.                     
  336.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  337.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  338.                 }
  339.             }
  340.             
  341.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  342.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  343.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  344.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  345.             }
  346.             
  347.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  348.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  349.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  350.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  351.             }
  352.             
  353.             var g:Graphics = sprite.graphics;
  354.             g.clear();
  355.             g.beginBitmapFill(floorTexture);
  356.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  357.             g.endFill();
  358.             displayBuffer.draw(sprite);
  359.             
  360.             g.clear();
  361.             g.lineStyle(1, WIREFRAME_COLOR);
  362.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  363.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  364.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  365.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  366.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  367.             
  368.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  369.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  370.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  371.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  372.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  373.             
  374.             g.clear();
  375.             g.beginFill(FIREWORK_COLOR);
  376.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  377.             g.endFill();
  378.             displayBuffer.draw(sprite);
  379.         }
  380.         
  381.         private const FIREWORK_RADIUS:Number = 8;
  382.         private const FIREWORK_HEIGHT:Number = 40;
  383.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  384.         
  385.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  386.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  387.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  389.         
  390.         private function createFireworkModel():void
  391.         {
  392.             const SEGMENT:int = 8;
  393.             for (var i:int = 0; i < SEGMENT; i++) {
  394.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  395.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  396.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  397.                 fireworkVertices.push(x, 0, z);
  398.                 
  399.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  400.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  401.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  402.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  403.                 fireworkIndices.push(i2, i0, i1);
  404.                 fireworkIndices.push(i1, i3, i2);
  405.             }
  406.         }
  407.     }
  408. }
noswf
Get Adobe Flash Player