forked from: 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 selflash ( http://wonderfl.net/user/selflash )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4hQL
*/
// forked from clockmaker's 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)
*/
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 {
private static var _p0:Point=new Point();
private static var _p1:Point=new Point();
private static var _p2:Point=new Point();
private static var _a0:Point=new Point();
private static var _a1:Point=new Point();
private static var _a2:Point=new Point();
public static function drawTriangles(g:Graphics, bitmapData:BitmapData, vertices:Array /*Number*/, indices:Array /*int*/, uvtData:Array /*Number*/):void {
var w:Number=bitmapData.width;
var h:Number=bitmapData.height;
var l:int=indices.length;
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 < l; i += 3) {
_p0.x=w * uvtData[ indices[ i ] * 2 ];
_p0.y=h * uvtData[ indices[ i ] * 2 + 1 ];
_p1.x=w * uvtData[ indices[ i + 1 ] * 2 ];
_p1.y=h * uvtData[ indices[ i + 1 ] * 2 + 1 ];
_p2.x=w * uvtData[ indices[ i + 2 ] * 2 ];
_p2.y=h * uvtData[ indices[ i + 2 ] * 2 + 1 ];
_a0.x=vertices[ indices[ i ] * 2 ];
_a0.y=vertices[ indices[ i ] * 2 + 1 ];
_a1.x=vertices[ indices[ i + 1 ] * 2 ];
_a1.y=vertices[ indices[ i + 1 ] * 2 + 1 ];
_a2.x=vertices[ indices[ i + 2 ] * 2 ];
_a2.y=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 var _matrixA:Matrix=new Matrix();
private static var _matrixB:Matrix=new Matrix();
private static var _matrix:Matrix=new Matrix();
private static function _buildTransformMatrix(
a0:Point, a1:Point, a2:Point,
b0:Point, b1:Point, b2:Point):Matrix {
_matrixA.identity();
_matrixA.a=a1.x - a0.x;
_matrixA.b=a1.y - a0.y;
_matrixA.c=a2.x - a0.x;
_matrixA.d=a2.y - a0.y;
_matrixA.invert();
_matrixB.identity();
_matrixB.a=b1.x - b0.x;
_matrixB.b=b1.y - b0.y;
_matrixB.c=b2.x - b0.x;
_matrixB.d=b2.y - b0.y;
_matrix.identity();
_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);
}
}