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

Matrix3D.interpolate developments

Get Adobe Flash player
by makc3d 24 Sep 2011
  • Forked from yonatan's Matrix3D.interpolate - umhr vs. Adobe
  • Diff: 95
  • Related works: 2
  • Talk

    yonatan at 24 Sep 2011 03:38
    Andy Zupko also suggested a very simple workaround; set all scales to 1, call interpolate() and then interpolate scale values manually, see http://wonderfl.net/c/rVRb
    yonatan at 24 Sep 2011 03:43
    Btw, where are all these developments taking place? last I heard my bug (FP-2041) got marked "Retired" whatever that means...
    makc3d at 24 Sep 2011 03:46
    Flare3D guy mentioned the issue to Adobe dev (David) on prerelease forum. David have not heared about the issue until only few days ago.
    Embed
/**
 * Copyright makc3d ( http://wonderfl.net/user/makc3d )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3LuF
 */

// 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);
	}
}