MIKUMIKU BLUR DEMO
東京てら子7 『夏休みの自由研究発表』の発表その2
* http://atnd.org/events/6936
* PV3Dで(モーション)ブラーをかけられるかを試したものです
* みんな大好き初音ミクのモデルデータをブラーってみました。
* ぶっちゃけ重いです
* ネギ振り/髪揺れつき
* ただの残像ではないので、ネギ振り/髪揺れにはブラーがかかっていません
* あくまで、カメラの動きにのみブラーがかかっています
/**
* Copyright fumix ( http://wonderfl.net/user/fumix )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/lYTe
*/
/*
* 東京てら子7 『夏休みの自由研究発表』の発表その2
* http://atnd.org/events/6936
* PV3Dで(モーション)ブラーをかけられるかを試したものです
* みんな大好き初音ミクのモデルデータをブラーってみました。
* ぶっちゃけ重いです
* ネギ振り/髪揺れつき
* ただの残像ではないので、ネギ振り/髪揺れにはブラーがかかっていません
* あくまで、カメラの動きにのみブラーがかかっています
*/
package {
import org.libspark.betweenas3.easing.Sine;
import flash.filters.BlurFilter;
import org.libspark.betweenas3.easing.Cubic;
import org.libspark.betweenas3.core.easing.CubicEaseInOut;
import flash.geom.Point;
import flash.display.SpreadMethod;
import flash.geom.Matrix;
import flash.display.GradientType;
import flash.display.Shape;
import org.papervision3d.render.QuadrantRenderEngine;
import org.libspark.betweenas3.tweens.ITweenGroup;
import org.libspark.betweenas3.tweens.ITween;
import org.libspark.betweenas3.core.tweens.groups.SerialTween;
import org.libspark.betweenas3.BetweenAS3;
import org.papervision3d.events.FileLoadEvent;
import org.papervision3d.objects.DisplayObject3D;
import net.hires.debug.Stats;
import com.bit101.components.HUISlider;
import com.bit101.components.Label;
import flash.display.Bitmap;
import flash.geom.ColorTransform;
import flash.display.BitmapData;
import org.papervision3d.core.math.Number3D;
import flash.events.MouseEvent;
import flash.display.DisplayObject;
import flash.display.StageQuality;
import flash.events.Event;
import org.papervision3d.objects.parsers.DAE;
import org.papervision3d.view.BasicView;
[SWF(backgroundColor="#FFFFFF", frameRate="15", width="465", height="465")]
public class LoadCollada extends BasicView
{
private var model:DAE;
private var _negi:DisplayObject3D;
private var _arm:DisplayObject3D;
private var _far : DisplayObject3D;
private var _view : BitmapData;
private var _colorTransBlur : ColorTransform;
private var _stats : Stats;
private var _colorTrans : ColorTransform;
private var _kami : DisplayObject3D;
public function LoadCollada() {
// flash init
stage.quality = StageQuality.MEDIUM;
//BG設置
var bg : Shape = new Shape();
addChildAt(bg, 0);
var gradType:String = GradientType.LINEAR;
var gradColors:Array = [ 0xFFFFFF , 0xE8E8E8 ];
var gradAlphas:Array = [ 1, 1 ];
var gradRadios:Array = [ 0, 255 ];
var gradMrx:Matrix = new Matrix( );
gradMrx.createGradientBox( stage.stageWidth, stage.stageHeight , Math.PI/2, 0,0);
var gradSpread:String = SpreadMethod.PAD;
bg.graphics.beginGradientFill( gradType , gradColors , gradAlphas , gradRadios , gradMrx ,gradSpread);
bg.graphics.drawRect( 0 , 0, stage.stageWidth, stage.stageHeight );
//view設置
_view = new BitmapData(stage.stageWidth, stage.stageHeight);
addChild(new Bitmap(_view));
//ラベル設置
var la : Label = new Label(this, 8, 4, "MIKUMIKU BLUR DEMO");
la.scaleX = la.scaleY = 2;
var la2:Label = new Label(this, 10, 30, "PLASE DRAG STAGE");
//stats設置
_stats = new Stats();
_stats.x = stage.stageWidth - 78;
_stats.y = 8;
addChild(_stats);
//ColorTransform設定
_colorTransBlur = new ColorTransform();
_colorTrans = new ColorTransform(1, 1, 1, 0.0);
// DAEクラスのインスタンスmodelを作成
model = new DAE();
// daeファイルを読み込む。これだけでOK。めっちゃ簡単。
// negimiku.daeファイルは、miku.pngを読むように設定されているのでマテリアルとかもいらない。
model.load("http://www.planet-ape.net/pv3d/negimiku2.dae");
model.addEventListener( FileLoadEvent.LOAD_COMPLETE, compCollada );
// サイズ調整 (今回はモデルが1つなのでこれで平気そうにみえる。ホントはmodelを大きくしたい)
model.scale = 45;
model.y = -100;
camera.y = 400;
// シーンにaddChild
scene.addChild(model);
//viewportをリムーブ
removeChild(viewport);
}
/**
* colladaファイルの読み込み完了
* @param event
*/
private function compCollada(event : FileLoadEvent) : void {
var dae_rootNode:DisplayObject3D = model.getChildByName("COLLADA_Scene");
//ネギと腕を取りだす
_negi = dae_rootNode.getChildByName('negi');
_arm = dae_rootNode.getChildByName('R_arm');
_far = dae_rootNode.getChildByName('miku_far');
_kami = dae_rootNode.getChildByName('miku_kami');
//ネギを腕にaddChildし直し(位置の調整も)
dae_rootNode.removeChildByName('negi');
_negi.x = -1.5;
_negi.y = -6.5;
_negi.z = 1.0;
_arm.addChild(_negi);
//髪アニメ
var kamiAnim1:ITween = BetweenAS3.tween(_kami, {rotationX:10},{rotationX:-5},0.5, Sine.easeInOut);
var kamiAnim2:ITween = BetweenAS3.tween(_kami, {rotationX:-5},{rotationX:10},0.5, Sine.easeInOut);
var kamiSerial:ITween = BetweenAS3.serial(kamiAnim1,kamiAnim2);
kamiSerial.stopOnComplete = false;
kamiSerial.play();
// render and loop
addEventListener(Event.ENTER_FRAME, loop);
// mouse interactive
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function loop(event : Event) : void {
// Mouse Interactive
easePitchOld = easePitch;
easeYawOld = easeYaw;
easePitch += (cameraPitch - easePitch) * 0.4;
easeYaw += (cameraYaw - easeYaw) * 0.4;
easePitchDiff = (easePitch - easePitchOld) / 6;
easeYawDiff = (easeYaw - easeYawOld) / 6;
_view.lock();
_view.colorTransform(_view.rect, _colorTrans);
for(var j : int = 1;j <= 6;j++) {
camera.x = 1200 * Math.sin((easeYawOld + easeYawDiff * j) * Number3D.toRADIANS);
camera.z = 1200 * Math.cos((easeYawOld + easeYawDiff * j) * Number3D.toRADIANS);
camera.y = 40 * (easePitchOld + easePitchDiff*j);
singleRender();
_colorTransBlur.alphaOffset = -255*(6 - j) / 6;
_view.draw(viewport, null, _colorTransBlur);
}
_view.unlock();
}
// ----------------------------------------------
// Mouse Interactive
// ----------------------------------------------
private var isOribiting : Boolean;
private var cameraPitch : Number = 10;
private var cameraYaw : Number = 90;
private var previousMouseX : Number;
private var previousMouseY : Number;
private var easePitch : Number = 270;
private var easeYaw : Number = 90;
private var easePitchOld : Number = 270;
private var easeYawOld : Number = 90;
private var easePitchDiff : Number;
private var easeYawDiff : Number;
private function onMouseDown(event : MouseEvent) : void {
isOribiting = true;
previousMouseX = event.stageX;
previousMouseY = event.stageY;
singleRender();
}
private function onMouseUp(event : MouseEvent) : void {
isOribiting = false;
//ネギ振りアニメ
var anim:ITween;
var negiAnim:ITween = BetweenAS3.tween(_negi, {rotationX:35},{rotationX:0},0.3);
var negiSerial:ITween = BetweenAS3.serial(negiAnim,BetweenAS3.reverse(negiAnim));
var armAnim:ITween = BetweenAS3.tween(_arm, {rotationX:45},{rotationX:0},0.3,Cubic.easeInOut);
var armAnim2:ITween = BetweenAS3.tween(_arm, {rotationX:360},{rotationX:0},0.4,Cubic.easeInOut);
var armSerial:ITween = BetweenAS3.serial(armAnim,BetweenAS3.reverse(armAnim));
if(Math.random()>0.2){
anim = BetweenAS3.parallel(negiSerial, armSerial);
}else{
anim = BetweenAS3.parallel(armAnim2);
}
anim.play();
}
private function onMouseMove(event : MouseEvent) : void {
var differenceX:Number = event.stageX - previousMouseX;
var differenceY:Number = event.stageY - previousMouseY;
if(isOribiting) {
cameraPitch += differenceY * 0.3;
cameraYaw += differenceX * 0.3;
cameraPitch = Math.max(5, Math.min(cameraPitch, 360));
previousMouseX = event.stageX;
previousMouseY = event.stageY;
}
}
}
}