In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: プチ高速化:外部SWFアニメから画像の輪郭抽出してPixel表示 feat.chibitami

1.外部SWFから輪郭を取得する。
* 2.Papervision3DのPixcel3Dで描画 
* 
* @author yooKo@serialField
* @graphic chibitami
* @version 2.0
* Let's Click!
* Click毎に3Dエフェクトが切り替わるお~~
* 
* 2009/10/13 13:49
* swfアニメの素材を変更
*  chibitami さんのswfアニメのモーションがかなり見栄えがよくサンプルに
* ちょうどよかったので許可を頂いてお借りしました。
* 画像元
* 【CHiBiTAMi.NET/WORKS/】
* http://chibitami.net/works/
* 【Twitter】
* http://twitter.com/chibitami
* 

追記 by clockmaker

したこと
・stage.quality 
・bitmapDataのlockとunclock

やったら効果あるんじゃないかと思うこと
・画像解析の結果を予め配列に格納
・Papervision3D(Pixels3D)を使わず、2DのBitmapDataに書き込んで、
 それをFlash 10の3Dで回転させるとか
Get Adobe Flash player
by soundkitchen 13 Oct 2009

    Tags

    3D
    Embed
/**
 * Copyright soundkitchen ( http://wonderfl.net/user/soundkitchen )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/bYkr
 */

// forked from yooKo's 外部SWFアニメから画像の輪郭抽出してPixel表示 feat.chibitami
// forked from yooKo's 外部SWFアニメから画像の輪郭抽出してPixel表示
/**
 * 1.外部SWFから輪郭を取得する。
 * 2.Papervision3DのPixcel3Dで描画 
 * 
 * @author yooKo@serialField
 * @graphic chibitami
 * @version 2.0
 * Let's Click!
 * Click毎に3Dエフェクトが切り替わるお~~
 * 
 * 2009/10/13 13:49
 * swfアニメの素材を変更
 *  chibitami さんのswfアニメのモーションがかなり見栄えがよくサンプルに
 * ちょうどよかったので許可を頂いてお借りしました。
 * 画像元
 * 【CHiBiTAMi.NET/WORKS/】
 * http://chibitami.net/works/
 * 【Twitter】
 * http://twitter.com/chibitami
 * 
 **/
 
 /*

 追記 by clockmaker

 したこと
 ・stage.quality 
 ・bitmapDataのlockとunclock
 
 やったら効果あるんじゃないかと思うこと
・画像解析の結果を予め配列に格納
・Papervision3D(Pixels3D)を使わず、2DのBitmapDataに書き込んで、
 それをFlash 10の3Dで回転させるとか

 */
 
 
package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.filters.BitmapFilterQuality;
	import flash.geom.Point;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	//import flash.system.SecurityDomain;
	import flash.system.Security;
	
	import org.papervision3d.core.effects.BitmapLayerEffect;
	import org.papervision3d.core.effects.BitmapColorEffect;
	import org.papervision3d.core.effects.utils.BitmapClearMode;
	import org.papervision3d.core.geom.Pixels;
	import org.papervision3d.core.geom.renderables.Pixel3D;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.view.layer.BitmapEffectLayer;
	
	import net.hires.debug.Stats;

    import org.si.sion.SiONDriver;
    import org.si.sion.SiONData;
    import org.si.sion.utils.SiONPresetVoice;
	
	[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]

	public class Pixcel3DAnime extends BasicView {
		private const IMAGE_URL:String = "http://selflash.jp/wonderfl/dance_girl.swf";
		//private const FILTER_BLUR:BlurFilter = new BlurFilter(8, 8, BitmapFilterQuality.LOW);   	
		private const TRANSFORM_COLOR:ColorTransform = new ColorTransform(0, 0, 0, 0, 0, 0, 0, 0); 		
		private const CAMERA_DISTANCE:int = -200;
		
		private var _loader:Loader;
		private var _pixels:Pixels;
		private var _rotateX:Number = 0;
		private var _rotateY:Number = 0;
		private var _currentNum:int = 0;
		private var _bmd:BitmapData;
		private var _pre:Number;
		private var _a:Number;
		private var _y:Number;
		private var _x:Number;
		private var _c:uint;
		private var _vx:Number = 0;
		private var _xx:Number = 0;
		private var _vy:Number = 0;
		private var _yy:Number = 0;

        private var _driver:SiONDriver = new SiONDriver();
        private var _voices:SiONPresetVoice = new SiONPresetVoice();
		
		// ソース画像のどの部分を解析するか。画像をさしかえる時はここを任意の値に
		//解析する開始位置
		private const TRIMMING_LEFT:int = 0;
		private const TRIMMING_TOP:int = 0;		
		//解析する終わりの位置 
		private const TRIMMING_RIGHT:int = 280;
		private const TRIMMING_BOTTOM:int = 280;	
		//=====================================================
		
		//除外したい色
		//private var EXCLUSION_COLOR:int = 0xFFFFFF; //白で抜きたいよー
		private var EXCLUSION_COLOR:int = 0x00; //アルファで抜きたいよー
		// 中央に持ってくる為に使う
	    private const W:Number = (TRIMMING_RIGHT + TRIMMING_LEFT) * .5/*TRIMMING_LEFT + TRIMMING_RIGHT * .5*/;
	    private const H:Number = (TRIMMING_BOTTOM + TRIMMING_TOP) * .5/*TRIMMING_TOP + TRIMMING_BOTTOM * .5*/;
		
		//========================================================================
		// コンストラクタ	
		//========================================================================
		public function Pixcel3DAnime() {	
			super(0, 0, true, true);			
			stage.quality = StageQuality.LOW;
			/**
			 *crossdomainにやらSecurity.allowDomain()やらまだまだ理解が浅くてわかんなかった、、
			 * 読み込む事はできるがdraw()ができなくて悩んだ。
			 * 結局呼び出す子swfの1フレーム目にSecurity.allowDomain("*")と記述した事でおk。
			 * ※Security.allowDomain("http://www.selflash.jp/")ではダメだった・・この辺はなんでか分かんない
			 *  http://cocoasaurus.com/blog/2009/09/as3allowdomain-1.html
			 * ↑のリンク先の情報によると読み込む方と読み込まれる方の両方に Security.allowDomain() を記述しないといけないらしいが
			 * ↓はコメントアウトしても draw() 出来てる。これもなぜだかわかんない、、、
			 */ 
			//Security.allowDomain("*");
			if (!stage)
                addEventListener(Event.ADDED_TO_STAGE, init);
            else
                init();
        }
		//========================================================================
		// 画像の読み込み	
		//========================================================================
        private function init(e:Event = null):void {	
            removeEventListener(Event.ADDED_TO_STAGE, init);
			
			_loader = new Loader(); 
			_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
			_loader.load(new URLRequest(IMAGE_URL), new LoaderContext(true));
		}		
		//========================================================================
		// ロード完了後の処理
		//========================================================================
		private function onCompleteHandler(e:Event):void {
			e.target.removeEventListener(Event.COMPLETE, init);
			
			//こいつから毎回色、座標を解析する
			_bmd = new BitmapData(TRIMMING_RIGHT, TRIMMING_BOTTOM, true, 0xFFFFFF);
			//左下に表示するためのやつね
			var bmp:Bitmap = new Bitmap(_bmd, "auto", false);
			bmp.scaleX = .4;
			bmp.scaleY = .4;
			bmp.y = stage.stageHeight - bmp.height;		
			addChild(bmp);
			
			camera.z = CAMERA_DISTANCE;	
			
			var _layer:BitmapEffectLayer = new BitmapEffectLayer(viewport, stage.stageWidth, stage.stageHeight, true, 0, BitmapClearMode.CLEAR_PRE, false);
			viewport.containerSprite.addLayer(_layer);
			_layer.addEffect(new BitmapColorEffect(1.2, 1.2, 1.2, .5));
			//_layer.drawCommand.blendMode = BlendMode.ADD;
            //_layer.addEffect(new BitmapLayerEffect(new BlurFilter(8, 8, BitmapFilterQuality.MEDIUM), false));	
			_pixels = new Pixels(_layer);
			scene.addChild(_pixels);	

            var loop:SiONData = _driver.compile("t126; %6@0o3l4$cccc; %6@1o3$rcrc; %6@2v8l16$[crccrrcc]; %6@3v8o3$[rc8r8];");
            var voices:Array = _voices['valsound.percus'];
            loop.setVoice(0, voices[0]);
            loop.setVoice(1, voices[27]);
            loop.setVoice(2, voices[16]);
            loop.setVoice(2, voices[21]);

            _driver.play(loop);

			addEventListener(Event.ENTER_FRAME, upDate);
			addEventListener(MouseEvent.MOUSE_DOWN, onDownHandler);		
			
			startRendering();	
			
			addChild(new Stats());
		}	
		//========================================================================
		// 表示の切り替え
		// ここ失敗作。。切り替えの仕組みがしょぼすぎる・・・なんか挙動が変、、スマートな方法あったら教えてください、、
		//========================================================================
		private function onDownHandler(e:MouseEvent = null):void {
			_currentNum++;
			//if (_currentNum > 6) {
				//_currentNum = 0;
			//}
			if(_currentNum > 6)_currentNum = 0;
			
			_vx = (Math.random() - .5) * 200;
			_vy = (Math.random() - .5) * 200;
		}		
		//========================================================================
		// 常に行う処理
		//========================================================================
		private function upDate(e:Event):void {
			_rotateX += (- viewport.containerSprite.mouseX - _rotateX) * 0.1;
			_rotateY += (- viewport.containerSprite.mouseY - 170 - _rotateY) * 0.1;
			_pixels.rotationY = _rotateX;
			_pixels.rotationX = _rotateY;
			
			//_bmd.applyFilter(_bmd, _bmd.rect, new Point(), FILTER_BLUR); 
			
			 //_bmdの中身を毎回消すには↓のどっちかだけどnew BitmapData()するとやっぱり重い、、
			_bmd.colorTransform(_bmd.rect, TRANSFORM_COLOR);
			//_bmd = new BitmapData(TRIMMING_RIGHT, TRIMMING_BOTTOM, true, 0x00);
			
			_bmd.draw(_loader);
			_pixels.removeAllpixels();			
			
			/** エフェクトの切り替え
			 * =================================================================
			 * 基本的には createBody()で全体,createFrame()で枠組みのみを生成します。
			 * 引数の説明
			 * 1つ目はレイヤーのz座標。
			 * 2つ目はドットの細かさ。
			 * 3つ目の色を指定しないという事はBitmapDataから取得した色をそのまま使うという事です。
			 * 引数を調整したりcreateBody(),createFrame()を増やしたりして調整してください。
			 * ==================================================================	
			 */
			switch (_currentNum) {
				// ノーマル //////////////////////////////////////
                case 0: 
				    // swfから取得した色で全体を表示する1層のレイヤー画像を作成
				    createBody(0, 2);
                break;
				// 3D //////////////////////////////////////////
				case 1:
				    // 指定した色で表示をする5層のレイヤーからなる厚みのある画像を作成。bodyでframeをサンドイッチ
				    createBody(-9, 4, 0xFFCCFF33);
				    createFrame(-6, 5, 0xFFCCFF33);
				    createFrame(-3, 5, 0xFFCCFF33);
				    createFrame(0, 5, 0xFFCCFF33);
				    createFrame(3, 5, 0xFFCCFF33);
				    createFrame(6, 5, 0xFFCCFF33);
				    createBody(9, 4, 0xFFCCFF33);
				break;
				// シルエット /////////////////////////////////////
				case 2:
				    // 指定した色で全体を表示する1層のレイヤー画像を作成。
				    createBody(0, 3, 0xFFCCFF00);
				break;
				// フレーム //////////////////////////////////////
				case 3:
				    // 指定した色で枠組みを表示する1層のレイヤー画像を作成。
				    createFrame(0, 2, 0xFFCCFF99);
				break;
				// 地震エフェクト? /////////////////////////////////
				case 4:
				    // 指定した色で枠組みを表示する1層のレイヤー画像を作成。
				    createBody(0, 3, 0, ((Math.random() - .5) * 50));
				break;
				// ディスコエフェクト //////////////////////////////////
				case 5:
				    // 指定した色で枠組みを表示する1層のレイヤー画像を作成。
				    createBody(0, 3, ((Math.random() - .7) * 5), ((Math.random() - .5) * 50));
				break;
				//ノイズエフェクト /////////////////////////////////////
				case 6: 
				    // 指定した色で枠組みを表示する1層のレイヤー画像を作成。
				    createBody(0, 3, 0xFF33CC00, 0, true);
				break;
            };	
			_xx += (_vx - _xx ) * .1;
			_yy += (_vy - _yy ) * .1;
		}	
		//========================================================================
		// 中身を作成するメソッド
		// 呼び出されたら白以外全部解析する
		// ※ 引数に色の指定がなければ抽出した色を使う
		//========================================================================
		private function createBody(depth:Number = 0, distance:Number = 2, color:Number = NaN, disco:Number = 0, noise:Boolean = false):void {
                        _bmd.lock();
			for ( _y = TRIMMING_TOP; _y < TRIMMING_BOTTOM; _y += distance ) {
				for ( _x = TRIMMING_LEFT; _x < TRIMMING_RIGHT; _x += distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != EXCLUSION_COLOR) {
						_c = (color)?color:rgb2argb(_c, 1);
						if (noise) {
							depth = depth + ((Math.random() - .5) * 2);
						};
						_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth + disco));
					}
				}
			}
                        _bmd.unlock();
		}		
		//========================================================================
		// 枠組みを作成するメソッド
		// 呼び出されたらキャラクターの外枠だけ解析する
		// ※ 引数に色の指定がなければ抽出した色を使う
		//========================================================================
		private function createFrame(depth:Number = -4, distance:Number = 2, color:Number = NaN, noise:Number = 0):void {	
                        _bmd.lock();		
			for ( _y = TRIMMING_TOP; _y < TRIMMING_BOTTOM; _y += distance ) {
				for ( _x = TRIMMING_LEFT; _x < TRIMMING_RIGHT; _x += distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != EXCLUSION_COLOR) {
						_a = (_y == 0)?0:_x - W - _pre;
						if (_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _x - W;
					}
				}
			}
			
			for ( _x = TRIMMING_LEFT; _x < TRIMMING_RIGHT; _x += distance ) {
				for ( _y = TRIMMING_TOP; _y < TRIMMING_BOTTOM; _y += distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != EXCLUSION_COLOR) {
						_a = (_x == 0)?0:_y - H - _pre;
						if(_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _y - H;
					}
				}
			}
			
			for ( _y = TRIMMING_BOTTOM; _y > TRIMMING_TOP; _y -= distance ) {
				for ( _x = TRIMMING_RIGHT; _x > TRIMMING_LEFT; _x -= distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != EXCLUSION_COLOR) {
						_a = (_y == TRIMMING_TOP + TRIMMING_BOTTOM)?0:_x - W - _pre;
						if(_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _x - W;
					}
				}
			}
			
			for ( _x = TRIMMING_RIGHT; _x > TRIMMING_LEFT; _x -= distance ) {
				for ( _y = TRIMMING_BOTTOM; _y > TRIMMING_TOP; _y -= distance ) {
					_c = _bmd.getPixel( _x, _y );
					if (_c != EXCLUSION_COLOR) {
						_a = (_x == TRIMMING_LEFT + TRIMMING_RIGHT)?0:_y - H - _pre;
						if(_a > distance || _a < - distance) {
							_c = (color)?color:rgb2argb(_c, 1);
							_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
						}
						_pre = _y - H;
					}
				}
			}
                        _bmd.unlock();
		}		
		//========================================================================
		// RGBをARGBに変換する
		//========================================================================
		private function rgb2argb(rgb:uint, alpha:Number):uint {
            return ((alpha * 0xff) << 24) + rgb;
        }
	}
}