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

3D Object rotation by Quaternion and Tweener

3Dオブジェクトをマウスの向きに合わせて回転させる
* 軸回転ではなく、クォータニオンを使って回転を制御
* 
* ついでにTweenerで姿勢制御をアニメーションさせてみる
* Cubeをドラッグで回転させた後、
* resetボタンを押すとアニメーションしながら初期値に戻る
* 
* [参考したサイト]
* http://yamasv.blog92.fc2.com/blog-entry-129.html
* http://yamasv.blog92.fc2.com/blog-entry-146.html
* http://blog.r3c7.net/?p=152
* http://forum.papervision3d.org/viewtopic.php?f=20&t=690
/**
 * Copyright fukusin ( http://wonderfl.net/user/fukusin )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/4kEq
 */

/*
 * 3Dオブジェクトをマウスの向きに合わせて回転させる
 * 軸回転ではなく、クォータニオンを使って回転を制御
 * 
 * ついでにTweenerで姿勢制御をアニメーションさせてみる
 * Cubeをドラッグで回転させた後、
 * resetボタンを押すとアニメーションしながら初期値に戻る
 * 
 * [参考したサイト]
 * http://yamasv.blog92.fc2.com/blog-entry-129.html
 * http://yamasv.blog92.fc2.com/blog-entry-146.html
 * http://blog.r3c7.net/?p=152
 * http://forum.papervision3d.org/viewtopic.php?f=20&t=690
 */
package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.text.*;
	//import fl.controls.*;
	//
    //import org.papervision3d.core.*;
    import org.papervision3d.core.geom.*;
    import org.papervision3d.core.math.*;
    import org.papervision3d.scenes.* ;
    import org.papervision3d.objects.*;
    import org.papervision3d.objects.primitives.*;
    import org.papervision3d.cameras.*;
    import org.papervision3d.materials.*;
    import org.papervision3d.materials.utils.*;
    import org.papervision3d.view.*;
    import org.papervision3d.render.*;
    import org.papervision3d.materials.special.* ;
	import org.papervision3d.events.*;
	//
	import caurina.transitions.Tweener;
	import net.hires.debug.Stats;
	//
	public class Main extends BasicView {
		//
		//
		//==========================
		//var
		//==========================
		private var mouseDown:Boolean = false;
		private var mousePos:Point;
		private var pose:org.papervision3d.core.math.Matrix3D;
		private var cube:Cube;
		private var reset_button:Sprite;
		private var rot:Object;
		private var vector:Object;
		//
		//
		//==========================
		//コンストラクタ
		//==========================
		public function Main():void
		{
			super(240, 400, true, true, CameraType.TARGET);
             rot = new Object();
             rot.x = 0;
             rot.y = 0;
             vector = new Object();
             vector.x = 0;
             vector.y = 0;
			//リセットボタン
			reset_button = new Sprite();
			reset_button.x = 10;
			reset_button.y = 10;
			addChild(reset_button);
			reset_button.graphics.beginFill(0x000000, 1);
			reset_button.graphics.drawRect(0, 0, 60, 30);
			var t:TextField = new TextField();
			//
			t.x = 10;
			t.y = 2;
			t.text = "reset";
			t.textColor = 0xffffff;
			t.selectable = false;
			//
		    var tf:TextFormat = new TextFormat();
			tf.size = 18;
			t.setTextFormat(tf);
			//
			reset_button.addChild(t);
			reset_button.addEventListener(MouseEvent.CLICK, onButtonClick); 
			//
			//addChild( new Stats() );
			//
			init3D();
		}
	    //
		//
		//==========================
		//init3D
		//==========================
		private function init3D():void
		{
			camera.x = 1500;
			camera.y = 600;
			camera.z = -1500;
			camera.focus = 2000;
			camera.zoom = 1;
			//
			var cm:ColorMaterial = new ColorMaterial(0x0099ff);
			var wm:WireframeMaterial = new WireframeMaterial(0x33ffff);
			var compo_material:CompositeMaterial = new CompositeMaterial();
			compo_material.addMaterial(cm);
			compo_material.addMaterial(wm);
			cube = new Cube(new MaterialsList( { all:compo_material } ), 200, 100, 300);
			scene.addChild(cube);
			//
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mousedown);
					
			startRendering();
		}
		//
		//
		//==========================
		//onButtonClick
		//==========================
		private function onButtonClick(e:MouseEvent):void 
		{
			removeEventListener(Event.ENTER_FRAME, throwing);
			//
			var m:org.papervision3d.core.math.Matrix3D = cube.transform;
			// 回転軸ベクトル
			var rv:Number3D = new Number3D( m.n32 - m.n23, m.n13 - m.n31, m.n21 - m.n12);
			rv.normalize();
			//
			// 回転角
			//Matrix3Dにtraceプロパティがなくなった(なんでだろ?)ので自作メソッドで対応
			//var rad:Number =  Math.acos((m.trace - 2 ) / 2);
			var rad:Number =  Math.acos((getTrace(m) - 2 ) / 2);
			// 逆回転して元の位置に戻す回転行列
			var r:org.papervision3d.core.math.Matrix3D = org.papervision3d.core.math.Matrix3D.rotationMatrix(rv.x, rv.y, rv.z, -rad);
			//cube.transform = org.papervision3d.core.math.Matrix3D.multiply(r, cube.transform);
			//
			//Tweenerで姿勢制御
			//------------
			var tm:org.papervision3d.core.math.Matrix3D = org.papervision3d.core.math.Matrix3D.multiply(r, cube.transform);
			//最初の姿勢クォータニオン生成
			var pos1:Quaternion = Quaternion.createFromOrthoMatrix(cube.transform);
			//最終的な姿勢クォータニオン生成
			var pos2:Quaternion = Quaternion.createFromOrthoMatrix(tm);
			pos1.normalize();
			pos2.normalize();
			//slerpを0→1にTweenさせるとアニメーションする
			//Quaternion.slerp(最初の姿勢クォータニオン, 最終的な姿勢クォータニオン,  slerp)
	         var extraObject:Object = {slerp:0};
            cube.extra = extraObject;
			Tweener.addTween(cube.extra, {time:1, slerp:1, onUpdate:function():void { cube.transform = Quaternion.slerp(pos1, pos2,  extraObject.slerp).matrix }, onComplete:endTween } );
			//------------
		}
		//
		//
		//==========================
		//endTween
		//==========================
		private function endTween():void
		{
			
		}
          //
         //
         //==========================
         //mousedown
         //==========================            
         private function mousedown(e:MouseEvent):void 
         {
             mouseDown = true;
             mousePos = new Point(stage.mouseX, stage.mouseY);
             pose = org.papervision3d.core.math.Matrix3D.clone(cube.transform);
             //
             removeEventListener(Event.ENTER_FRAME, throwing);
             //
             stage.addEventListener(MouseEvent.MOUSE_MOVE, mousemove);
             stage.addEventListener(MouseEvent.MOUSE_UP, mouseup);
         }
         //
         //
         //==========================
         //mousemove
         //==========================
         private function mousemove(e:MouseEvent):void{
             if (mouseDown) {
                 var rot_buffer:Object = Object({x:rot.x, y: rot.y});
                 //
                 rot.x = stage.mouseX -mousePos.x;
                 rot.y = stage.mouseY - mousePos.y;
                 //
                 vector.x = rot.x - rot_buffer.x;
                 vector.y = rot.y - rot_buffer.y;
                 //
                 rotate();
             }
         }
         //
         //
         //==========================
         //mouseup
         //==========================
         private function mouseup(e:MouseEvent):void 
         {
             mouseDown = false;
             addEventListener(Event.ENTER_FRAME, throwing);
             //
             stage.removeEventListener(MouseEvent.MOUSE_MOVE, mousemove);
             stage.removeEventListener(MouseEvent.MOUSE_UP, mouseup);
         }
         //
         //
         //==========================
         //throwing
         //==========================
         private function throwing(e:Event):void 
         {
             vector.x *= 0.9;
             vector.y *= 0.9;
             //
             if (Math.abs(vector.x) < 0.01 && Math.abs(vector.y) < 0.01) {
                 vector.x = 0;
                 vector.y = 0;
                 removeEventListener(Event.ENTER_FRAME, throwing);
             }else {
                 rot.x += vector.x;
                 rot.y += vector.y;
             }
             //
             rotate();
         }
         //
         //
         //==========================
         //rotate
         //==========================
         private function rotate():void 
         {
             // X方向(Y軸周り)に回転する回転行列
             var my:org.papervision3d.core.math.Matrix3D = org.papervision3d.core.math.Matrix3D.rotationMatrix(0, 1, 0, -0.02 * rot.x);
             // Y方向(X軸周り)に回転する回転行列
             var mx:org.papervision3d.core.math.Matrix3D = org.papervision3d.core.math.Matrix3D.rotationMatrix(1, 0, 0, -0.02 * rot.y);
             // 回転の合成
             var m:org.papervision3d.core.math.Matrix3D = org.papervision3d.core.math.Matrix3D.multiply(mx, my);
             cube.transform = org.papervision3d.core.math.Matrix3D.multiply(m, pose);
         }
 		//
		//
		//==========================
		//getTrace
		//==========================
		public function getTrace(m:org.papervision3d.core.math.Matrix3D):Number
		{
			return m.n11 + m.n22 + m.n33 + 1;
		}
     }
	//
	//
}