forked from: Matrix3D.interpolate developments
Comparison of interpolation techniques:
Green sprite uses Adobe's Matrix3D.interpolate function
Orange sprite uses umhr's Mtrx3D.interpolate function
Black sprite uses my interpolate function, which is umhr's interpolate with support for scaling
/**
* Copyright focusky.neugls ( http://wonderfl.net/user/focusky.neugls )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1wki
*/
// forked from makc3d's Matrix3D.interpolate developments
// forked from yonatan's Matrix3D.interpolate - umhr vs. Adobe
// forked from umhr's 【未完成】Matrix3D.interpolate()
/* Comparison of interpolation techniques:
Green sprite uses Adobe's Matrix3D.interpolate function
Orange sprite uses umhr's Mtrx3D.interpolate function
Black sprite uses my interpolate function, which is umhr's interpolate with support for scaling
*/
package {
import flash.display.Sprite;
import flash.events.*;
import flash.utils.*;
import flash.text.*;
import flash.geom.Matrix3D;
public class Test extends Sprite {
private var r:Sprite, adobe:Sprite, b:Sprite, umhr:Sprite, me:Sprite;
public function Test() {
var array:Array = [];
for each( var color:uint in [0xFF0000,0x00FF00,0x0000FF,0xFF8800,0x000000] ) {
var s:Sprite = new Sprite;
s.graphics.beginFill( color );
s.graphics.drawRect( 0, 0, 100, 100 );
s.graphics.endFill();
s.alpha = 0.5;
addChild(s);
array.push( s );
}
r = array[0]; // src (red)
b = array[2]; //
adobe = array[1]; // Adobe's interpolate (green)
umhr = array[3]; // umhr's interpolate (orange)
me = array[4]; // (black)
r.x = 100;
r.y = 30;
r.rotationY = r.rotationY = r.rotationZ = 40;
r.scaleY = 1.5;
r.scaleX = r.scaleZ = 0.5;
b.rotationX = -40;
b.x = b.y = 333;
addEventListener( Event.ENTER_FRAME, onEnter );
}
// use Matrix3D.interpolate to calculate a new matrix for g
private function onEnter( e:Event ):void {
var t:Number = Math.sin( getTimer()/1000 )/2+0.5;
umhr.transform.matrix3D = Mtrx3D.interpolate( r.transform.matrix3D, b.transform.matrix3D, t );
me.transform.matrix3D = Mtrx3D.myInterpolate( r.transform.matrix3D, b.transform.matrix3D, t );
adobe.transform.matrix3D = Matrix3D.interpolate( r.transform.matrix3D, b.transform.matrix3D, t );
}
}
}
class Mtrx3D {
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.geom.Orientation3D;
/** David Tristram's proposed fix... tsss */
public static function interpolate( src:Matrix3D, dst:Matrix3D, percent:Number ) : Matrix3D
{
var srcComp : Vector.<Vector3D> = src.decompose( Orientation3D.QUATERNION );
var dstComp : Vector.<Vector3D> = dst.decompose( Orientation3D.QUATERNION );
var resComp : Vector.<Vector3D> = new Vector.<Vector3D>;
resComp[0] = lerp( srcComp[0], dstComp[0], percent );
resComp[1] = lerp( srcComp[1], dstComp[1], percent );
resComp[2] = lerp( srcComp[2], dstComp[2], percent );
// do a four-component normalize, can’t use Vector3D.normalize()
var q : Vector3D = resComp[ 1 ];
var qMag : Number = Math.sqrt( q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w );
q.x /= qMag;
q.y /= qMag;
q.z /= qMag;
q.w /= qMag;
resComp[1] = q;
var res : Matrix3D = new Matrix3D();
res.recompose( resComp, Orientation3D.QUATERNION );
return res;
}
/** I think they are going to use slerp actually */
private static function lerp( v1 : Vector3D, v2 : Vector3D, frac : Number ) : Vector3D
{
return new Vector3D(
v1.x += ( v2.x - v1.x ) * frac,
v1.y += ( v2.y - v1.y ) * frac,
v1.z += ( v2.z - v1.z ) * frac,
v1.w += ( v2.w - v1.w ) * frac
);
}
public static function myInterpolate(thisMat:Matrix3D,toMat:Matrix3D,percent:Number):Matrix3D{
var v0:Vector3D = thisMat.decompose("quaternion")[1];
var v1:Vector3D = toMat.decompose("quaternion")[1];
var cosOmega:Number = v0.w*v1.w + v0.x*v1.x + v0.y*v1.y + v0.z*v1.z;
if(cosOmega < 0){
v1.x = -v1.x;
v1.y = -v1.y;
v1.z = -v1.z;
v1.w = -v1.w;
cosOmega = -cosOmega;
}
var k0:Number;
var k1:Number;
if(cosOmega > 0.9999){
k0 = 1 - percent;
k1 = percent;
}else{
var sinOmega:Number = Math.sqrt(1 - cosOmega*cosOmega);
var omega:Number = Math.atan2(sinOmega,cosOmega);
var oneOverSinOmega:Number = 1/sinOmega;
k0 = Math.sin((1-percent)*omega)*oneOverSinOmega;
k1 = Math.sin(percent*omega)*oneOverSinOmega;
}
var scale_x:Number = thisMat.decompose("quaternion")[2].x*(1-percent) + toMat.decompose("quaternion")[2].x*percent;
var scale_y:Number = thisMat.decompose("quaternion")[2].y*(1-percent) + toMat.decompose("quaternion")[2].y*percent;
var scale_z:Number = thisMat.decompose("quaternion")[2].z*(1-percent) + toMat.decompose("quaternion")[2].z*percent;
var tx:Number = thisMat.decompose("quaternion")[0].x*(1-percent) + toMat.decompose("quaternion")[0].x*percent;
var ty:Number = thisMat.decompose("quaternion")[0].y*(1-percent) + toMat.decompose("quaternion")[0].y*percent;
var tz:Number = thisMat.decompose("quaternion")[0].z*(1-percent) + toMat.decompose("quaternion")[0].z*percent;
//trace(thisMat.decompose("quaternion")[2].x,toMat.decompose("quaternion")[2].x,scale_x)
var x:Number = v0.x*k0+v1.x*k1;
var y:Number = v0.y*k0+v1.y*k1;
var z:Number = v0.z*k0+v1.z*k1;
var w:Number = v0.w*k0+v1.w*k1;
var _q:Vector.<Number> = new Vector.<Number>(16,true);
_q[0] = (1-2*y*y-2*z*z)*scale_x;
_q[1] = (2*x*y+2*w*z)*scale_x;
_q[2] = (2*x*z-2*w*y)*scale_x;
_q[3] = 0;
_q[4] = 2*x*y-2*w*z*scale_y;
_q[5] = (1-2*x*x-2*z*z)*scale_y;
_q[6] = 2*y*z+2*w*x*scale_y;
_q[7] = 0;
_q[8] = 2*x*z+2*w*y*scale_z;
_q[9] = 2*y*z-2*w*x*scale_z;
_q[10] = (1-2*x*x-2*y*y)*scale_z;
_q[11] = 0;
_q[12] = tx;
_q[13] = ty;
_q[14] = tz;
_q[15] = 1;
//trace(_q)
var v:Vector3D = new Vector3D(v0.x*k0+v1.x*k1,v0.y*k0+v1.y*k1,v0.z*k0+v1.z*k1,v0.w*k0+v1.w*k1);
//var txyz:Vector3D = new Vector3D(tx,ty,tz);
//var m:Matrix3D=new Matrix3D();
//m.recompose(Vector.<Vector3D>([txyz,v,new Vector3D(scale_x,scale_y,scale_z)]),"quaternion");
//trace(m.rawData);
return new Matrix3D(_q);
}
}