forked from: forked from: [BetweenAS3] Papervision Matrix3D Tween
/**
* Copyright yonatan ( http://wonderfl.net/user/yonatan )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/db4c
*/
// forked from yonatan's forked from: [BetweenAS3] Papervision Matrix3D Tween
// forked from yonatan's [BetweenAS3] Papervision Matrix3D Tween
// forked from nitoyon's [BetweenAS3] Random Text Tween
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.*;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.*;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.PaperPlane;
import org.papervision3d.view.BasicView;
import frocessing.color.ColorHSV;
[SWF (backgroundColor="0xffffff")]
public class FlashTest extends BasicView {
public function FlashTest() {
_camera.zoom = 30;
var light:PointLight3D;
light = new PointLight3D(false);
light.y = 1000;
var planes:Array = [];
for(var i:uint=0; i < 64; i++) {
var hsv:ColorHSV = new ColorHSV(i*4, 0.9, 0.8);
var mat:FlatShadeMaterial = new FlatShadeMaterial(light, hsv.value32);
mat.doubleSided = true;
var p:PaperPlane = new PaperPlane(mat);
scene.addChild(p);
planes.push(p);
}
function doTweens():void {
var sx:Number = Math.random()*3;
var sy:Number = Math.random()*3;
var sz:Number = Math.random()*2;
var yaw:Number = Math.random()*1000;
var pitch:Number = Math.random()*1200;
var dist:Number = Math.random()*500 + 250;
var lookAt0:Boolean = Math.random() < 0.5;
for(var i:uint=0; i < planes.length; i++) {
var n:Number = i/planes.length - 0.5;
var dst:DisplayObject3D = new DisplayObject3D;
dst.yaw(yaw-yaw*n);
dst.pitch(pitch-pitch*n);
dst.moveForward(dist);
dst.scaleX = sx;
dst.scaleY = sy;
dst.scaleZ = sz;
if(lookAt0) {
dst.lookAt(DisplayObject3D.ZERO);
}
dst.copyTransform(dst);
var tween:PVMatrixTween = new PVMatrixTween();
tween.target = planes[i];
tween.easing = Sine.easeOut;
tween.matrix = dst.transform;
tween.time = 1;
BetweenAS3.delay(tween, Math.abs(i-32)*20/1000).play();
}
}
setInterval(doTweens, 1750);
addEventListener("enterFrame", function(e:*):void {
light.x = _camera.x = Math.sin(getTimer()/3000) * 1000;
light.z = _camera.z = Math.cos(getTimer()/3000) * 1000;
});
startRendering();
}
}
}
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.core.easing.IEasing;
import org.libspark.betweenas3.core.ticker.ITicker;
import org.libspark.betweenas3.core.tweens.AbstractTween;
import org.libspark.betweenas3.core.tweens.IITween;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.Quaternion;
import org.papervision3d.objects.DisplayObject3D;
class PVMatrixTween extends AbstractTween
{
/**
* static ITicker cache.
*/
private static var _ticker:ITicker;
/**
* initial Matrix3D storage.
*/
private var _start:Matrix3D;
/**
* DisplayObject3D.
*/
public function get target():DisplayObject3D { return _target; }
public function set target(value:DisplayObject3D):void {
value.copyTransform(value); // hack -- make sure the do3d's transform is up to date.
_start = Matrix3D.clone(value.transform);
_target = value;
}
private var _target:DisplayObject3D;
/**
* Tween easing.
*/
public function get easing():IEasing { return _easing; }
public function set easing(value:IEasing):void { _easing = value; }
private var _easing:IEasing;
/**
* Destination transform matrix.
*/
public function get matrix():Matrix3D { return _matrix; }
public function set matrix(value:Matrix3D):void { _matrix = value; }
private var _matrix:Matrix3D;
/**
* Set or get duration.
*/
public function get time():Number { return _duration; }
public function set time(value:Number):void { _duration = value; }
/**
* Constructor.
*
* @param duration sleep duration.
* @param ticker ticker object.
* @param position initial position.
*/
public function PVMatrixTween(ticker:ITicker = null, position:Number = 0) {
if (!_ticker) {
// create tmp tween to get the BetweenAS3's static ticker.
var tmpTween:IITween = BetweenAS3.parallel() as IITween;
_ticker = tmpTween.ticker;
}
super(ticker || _ticker, position);
}
/**
* 更新処理を行う。
*/
protected override function internalUpdate(time:Number):void
{
// check
if (!_target) { throw new Error("target is not set"); }
if (!_easing) { throw new Error("easing is not set"); }
if (!_matrix) { throw new Error("matrix is not set"); }
// get the factor (0.0~1.0)
var factor:Number = 0.0;
if (time > 0.0) {
if (time < _duration) {
factor = _easing.calculate(time, 0.0, 1.0, _duration);
}
else {
factor = 1.0;
}
}
// update the matrix
_target.copyTransform(interpolateMatrix3D(_start, _matrix, factor));
}
/**
* 3D utils
*/
private function interpolateMatrix3D(thisMat:Matrix3D,toMat:Matrix3D,percent:Number):Matrix3D{
// decomposition:
// we need to give Quaternion.createFromMatrix rotation-only matrices (with normalized axii),
// otherwise we choke on scaling matrices
var thisQuat:Quaternion = Quaternion.createFromMatrix( getRotationMatrix( thisMat ) );
var toQuat:Quaternion = Quaternion.createFromMatrix( getRotationMatrix( toMat ) );
var thisScale:Number3D = getScaleFromMatrix3D( thisMat );
var toScale:Number3D = getScaleFromMatrix3D( toMat );
var thisTranslation:Number3D = new Number3D( thisMat.n14, thisMat.n24, thisMat.n34 );
var toTranslation:Number3D = new Number3D( toMat.n14, toMat.n24, toMat.n34 );
// interpolation:
var scale_x:Number = thisScale.x*(1-percent) + toScale.x*percent;
var scale_y:Number = thisScale.y*(1-percent) + toScale.y*percent;
var scale_z:Number = thisScale.z*(1-percent) + toScale.z*percent;
var tx:Number = thisTranslation.x*(1-percent) + toTranslation.x*percent;
var ty:Number = thisTranslation.y*(1-percent) + toTranslation.y*percent;
var tz:Number = thisTranslation.z*(1-percent) + toTranslation.z*percent;
var q:Quaternion = Quaternion.slerp( thisQuat, toQuat, percent );
// recomposition:
var x:Number = q.x;
var y:Number = q.y;
var z:Number = q.z;
var w:Number = q.w;
var ret:Matrix3D = new Matrix3D;
// apparently mxmlc optimizes away the duplicate multiplications,
// so there's no need to do it manually
ret.n11 = (1-2*y*y-2*z*z)*scale_x;
ret.n21 = (2*x*y+2*w*z)*scale_x;
ret.n31 = (2*x*z-2*w*y)*scale_x;
ret.n41 = 0;
ret.n12 = (2*x*y-2*w*z)*scale_y;
ret.n22 = (1-2*x*x-2*z*z)*scale_y;
ret.n32 = (2*y*z+2*w*x)*scale_y;
ret.n42 = 0;
ret.n13 = (2*x*z+2*w*y)*scale_z;
ret.n23 = (2*y*z-2*w*x)*scale_z;
ret.n33 = (1-2*x*x-2*y*y)*scale_z;
ret.n43 = 0;
ret.n14 = tx;
ret.n24 = ty;
ret.n34 = tz;
ret.n44 = 1;
return ret;
}
// scale values can't be negative!
private function getScaleFromMatrix3D( m:Matrix3D ):Number3D {
var x:Number = Math.sqrt( m.n11*m.n11 + m.n21*m.n21 + m.n31*m.n31 );
var y:Number = Math.sqrt( m.n12*m.n12 + m.n22*m.n22 + m.n32*m.n32 );
var z:Number = Math.sqrt( m.n13*m.n13 + m.n23*m.n23 + m.n33*m.n33 );
return( new Number3D( x, y, z ) );
}
// returns a rotation-only matrix (no scale/translate)
private function getRotationMatrix( m:Matrix3D ):Matrix3D {
var scale:Number3D = getScaleFromMatrix3D( m );
return( new Matrix3D ( [
m.n11 / scale.x, m.n12 / scale.y, m.n13 / scale.z, 0,
m.n21 / scale.x, m.n22 / scale.y, m.n23 / scale.z, 0,
m.n31 / scale.x, m.n32 / scale.y, m.n33 / scale.z, 0,
0, 0, 0, 1
] ) );
}
}