Genie effect (Flash Player 9 or 10 compare version)
Ginny Effect (Flash Player 9 or 10 compare version)
* drawTriangles の速度検証
*
* -- run about --
* StageQuality - HIGH
* BitmapSmoothing - true
*
* -- 考察 --
* ・drawTrianglesのほうが処理負荷が軽い
* ・smoothingあるなし、ともに同じ結果が確認している
* ・drawTrianglesを使うと妙なスムージングが適用される(解決法求む)
*
* Photo by
* http://www.flickr.com/photos/88403964@N00/179493851/ (by clockmaker)
/**
* Copyright clockmaker ( http://wonderfl.net/user/clockmaker )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/gf3B
*/
/**
* Ginny Effect (Flash Player 9 or 10 compare version)
* drawTriangles の速度検証
*
* -- run about --
* StageQuality - HIGH
* BitmapSmoothing - true
*
* -- 考察 --
* ・drawTrianglesのほうが処理負荷が軽い
* ・smoothingあるなし、ともに同じ結果が確認している
* ・drawTrianglesを使うと妙なスムージングが適用される(解決法求む)
*
* Photo by
* http://www.flickr.com/photos/88403964@N00/179493851/ (by clockmaker)
*/
package {
import com.bit101.components.RadioButton;
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import net.hires.debug.Stats;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;
[SWF(width="465", height="465", frameRate="60", backgroundColor=0x0)]
public class Main extends Sprite {
public function Main():void {
// init
stage.quality = StageQuality.HIGH;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
graphics.beginFill(0x0);
graphics.drawRect(0, 0, 465, 465);
// load
var context:LoaderContext = new LoaderContext(true);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, compHandler);
loader.load(new URLRequest(IMAGE_URL), context);
// stats
addChild(new Stats());
// ui
radioA = new RadioButton(this, 10, 400, "FLASH PLAYER 10 (DRAW TRIANGLES)", true, onRadioChange);
radioB = new RadioButton(this, 10, 430, "FLASH PLAYER 9 (CUSTOM)", false, onRadioChange);
}
private const IMAGE_URL:String = "http://farm1.static.flickr.com/44/179493851_5775990a83.jpg";
private const IMG_H:int = 375;
private const IMG_W:int = 500;
private const SEGMENT:int = 30;
private var isFp10Selected:Boolean = true;
private var isHide:Boolean = false;
private var isShift:Boolean = false;
private var loader:Loader;
private var radioA:RadioButton;
private var radioB:RadioButton;
private var sprite:Sprite;
private var vertexs:Array;
private function compHandler(e:Event):void {
sprite = new Sprite();
addChildAt(sprite, 0);
vertexs = [];
for (var xx:int = 0; xx <= SEGMENT; xx++) {
vertexs[ xx ] = [];
for (var yy:int = 0; yy <= SEGMENT; yy++) {
vertexs[ xx ][ yy ] = new Point(xx * IMG_W / SEGMENT, yy * IMG_H / SEGMENT);
}
}
draw();
addEventListener(Event.ENTER_FRAME, draw);
stage.addEventListener(MouseEvent.CLICK, clickHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
private function clickHandler(e:MouseEvent):void {
var tweens:Array = [];
var xx:int, yy:int, delay:Number;
var px:Number = SEGMENT * (mouseX / IMG_W);
var py:Number = SEGMENT * (mouseY / IMG_H);
if (!isHide) {
for (xx = 0; xx <= SEGMENT; xx++) {
for (yy = 0; yy <= SEGMENT; yy++) {
vertexs[ xx ][ yy ] = new Point(xx * IMG_W / SEGMENT, yy * IMG_H / SEGMENT);
delay = Math.sqrt((xx - px) * (xx - px) + (yy - py) * (yy - py)) / 40;
tweens.push(
BetweenAS3.delay(
BetweenAS3.tween(vertexs[ xx ][ yy ], {
x: Math.round(px * IMG_W / SEGMENT),
y: Math.round(py * IMG_H / SEGMENT)
}, null, delay, Cubic.easeIn),
delay / 2
)
)
}
}
} else {
var max:Number = 0;
for (xx = 0; xx <= SEGMENT; xx++) {
for (yy = 0; yy <= SEGMENT; yy++) {
vertexs[ xx ][ yy ] = new Point(px * IMG_W / SEGMENT, py * IMG_H / SEGMENT);
delay = Math.sqrt((xx - px) * (xx - px) + (yy - py) * (yy - py))
max = Math.max(max, delay);
}
}
for (xx = 0; xx <= SEGMENT; xx++) {
for (yy = 0; yy <= SEGMENT; yy++) {
delay = (max - Math.sqrt((xx - px) * (xx - px) + (yy - py) * (yy - py))) / 40;
tweens.push(
BetweenAS3.delay(
BetweenAS3.tween(vertexs[ xx ][ yy ], {
x: Math.round(xx * IMG_W / SEGMENT),
y: Math.round(yy * IMG_H / SEGMENT)
}, null, delay + 0.05, Quad.easeOut),
delay / 2
)
)
}
}
}
var itw:ITween = BetweenAS3.parallelTweens(tweens);
if (isShift)
itw = BetweenAS3.scale(itw, 5);
itw.play();
isHide = !isHide;
}
/**
* drawTriangles でテクスチャを貼り付けるメソッド
* 参考: http://wonderfl.net/code/e7e1e28a9f20d73f11f0bb02d3e4b5f512c7cc0f
*/
private function draw(e:Event = null):void {
var vertices:Array /* of Number */ = [];
var indices:Array /* of int */ = [];
var uvtData:Array /* of Number */ = [];
var xx:int, yy:int;
for (yy = 0; yy <= SEGMENT; yy++) {
for (xx = 0; xx <= SEGMENT; xx++) {
vertices.push(vertexs[ xx ][ yy ].x, vertexs[ xx ][ yy ].y);
uvtData.push(xx / SEGMENT, yy / SEGMENT);
}
}
for (yy = 0; yy < SEGMENT; yy++) {
for (xx = 0; xx < SEGMENT; xx++) {
indices.push(
xx + yy * (SEGMENT + 1),
xx + 1 + yy * (SEGMENT + 1),
xx + (yy + 1) * (SEGMENT + 1)
);
indices.push(
xx + 1 + yy * (SEGMENT + 1),
xx + 1 + (yy + 1) * (SEGMENT + 1),
xx + (yy + 1) * (SEGMENT + 1)
);
}
}
var g:Graphics = sprite.graphics;
g.clear();
if (isFp10Selected) {
var verticesV:Vector.<Number> = Vector.<Number>(vertices);
var indicesV:Vector.<int> = Vector.<int>(indices);
var uvtDataV:Vector.<Number> = Vector.<Number>(uvtData);
g.beginBitmapFill(Bitmap(loader.content).bitmapData, null, false, true);
g.drawTriangles(verticesV, indicesV, uvtDataV);
g.endFill();
} else {
GraphicUtil.drawTriangles(g, Bitmap(loader.content).bitmapData, vertices, indices, uvtData);
}
}
/**
* Shiftキーを押してるとスローモーションになる
* macの挙動と同じように
*/
private function keyUpHandler(e:KeyboardEvent):void {
if (e.keyCode == 16)
isShift = false;
}
private function keyDownHandler(e:KeyboardEvent):void {
if (e.keyCode == 16)
isShift = true;
}
private function onRadioChange(e:Event):void {
isFp10Selected = e.currentTarget == radioA;
e.stopPropagation();
}
}
}
import flash.display.*;
import flash.geom.*;
class GraphicUtil {
public static function drawTriangles(g:Graphics, bitmapData:BitmapData, vertices:Array /*Number*/, indices:Array /*int*/, uvtData:Array /*Number*/):void {
if (vertices.length % 2 != 0)
throw new Error();
if (indices.length % 3 != 0)
throw new Error();
if (uvtData.length % 2 != 0)
throw new Error();
for (var i:int = 0; i < indices.length; i += 3) {
var p0:Point = new Point(bitmapData.width * uvtData[ indices[ i ] * 2 ], bitmapData.height * uvtData[ indices[ i ] * 2 + 1 ]);
var p1:Point = new Point(bitmapData.width * uvtData[ indices[ i + 1 ] * 2 ], bitmapData.height * uvtData[ indices[ i + 1 ] * 2 + 1 ]);
var p2:Point = new Point(bitmapData.width * uvtData[ indices[ i + 2 ] * 2 ], bitmapData.height * uvtData[ indices[ i + 2 ] * 2 + 1 ]);
var a0:Point = new Point(vertices[ indices[ i ] * 2 ], vertices[ indices[ i ] * 2 + 1 ]);
var a1:Point = new Point(vertices[ indices[ i + 1 ] * 2 ], vertices[ indices[ i + 1 ] * 2 + 1 ]);
var a2:Point = new Point(vertices[ indices[ i + 2 ] * 2 ], vertices[ indices[ i + 2 ] * 2 + 1 ]);
var matrix:Matrix = _buildTransformMatrix(p0, p1, p2, a0, a1, a2);
g.beginBitmapFill(bitmapData, matrix, false, true);
_drawTriangle(g, p0, p1, p2, matrix);
g.endFill();
}
}
private static function _buildTransformMatrix(
a0:Point, a1:Point, a2:Point,
b0:Point, b1:Point, b2:Point):Matrix {
var matrixA:Matrix = new Matrix(
a1.x - a0.x, a1.y - a0.y,
a2.x - a0.x, a2.y - a0.y);
matrixA.invert();
var matrixB:Matrix = new Matrix(
b1.x - b0.x, b1.y - b0.y,
b2.x - b0.x, b2.y - b0.y);
var matrix:Matrix = new Matrix();
matrix.translate(-a0.x, -a0.y); // (原点)へ移動
matrix.concat(matrixA); // 単位行列に変換(aの座標系の逆行列)
matrix.concat(matrixB); // bの座標系に変換
matrix.translate(b0.x, b0.y); // b0へ移動
return matrix;
}
private static function _drawTriangle(g:Graphics, p0:Point, p1:Point, p2:Point, matrix:Matrix):void {
p0 = matrix.transformPoint(p0);
p1 = matrix.transformPoint(p1);
p2 = matrix.transformPoint(p2);
// g.lineStyle(2, 0x808080); // debug
g.moveTo(p0.x, p0.y);
g.lineTo(p1.x, p1.y);
g.lineTo(p2.x, p2.y);
g.lineTo(p0.x, p0.y);
}
}