forked from: forked from: Fast texture extraction

by makc3d forked from forked from: Fast texture extraction (diff: 157)
Testing projected shape behavior (yet again sucks).
♥0 | Line 192 | Modified 2010-12-09 00:37:37 | MIT License
play

ActionScript3 source code

/**
 * Copyright makc3d ( http://wonderfl.net/user/makc3d )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cT5i
 */

package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	
	/**
	 * Testing projected shape behavior (yet again sucks).
	 */
	[SWF(width=465,height=465,backgroundColor=0)]
	public class HTest extends Sprite {
		public var anchors:Vector.<Anchor>;
		public var homography:Homography;
		public function HTest () {
			anchors = new Vector.<Anchor> (4, true);
			addChild (anchors [0] = new Anchor (100, 257));
			addChild (anchors [1] = new Anchor (122, 218));
			addChild (anchors [2] = new Anchor (131, 251));
			addChild (anchors [3] = new Anchor (111, 296));
			addChild (homography = new Homography);
			homography.x = homography.y = 232;
			stage.addEventListener (MouseEvent.MOUSE_MOVE, onMouseMove);
			onMouseMove (null);
		}
		public function onMouseMove (e:MouseEvent):void {
			if ((e == null) || e.buttonDown) {
				homography.update (
					new Point (anchors [0].x, anchors [0].y),
					new Point (anchors [1].x, anchors [1].y),
					new Point (anchors [2].x, anchors [2].y),
					new Point (anchors [3].x, anchors [3].y)
				);
			}
		}
	}
}

import flash.display.Sprite;
import flash.events.MouseEvent;
class Anchor extends Sprite {
	public function Anchor (x0:int, y0:int) {
		x = x0; y = y0;
		graphics.beginFill (0xFF7F00, 1);
		graphics.drawRect (-4, -4, 8, 8);
		graphics.drawRect (-2, -2, 4, 4);
		graphics.beginFill (0xFF7F00, 0);
		graphics.drawRect (-2, -2, 4, 4);
		useHandCursor = buttonMode = true;
		addEventListener (MouseEvent.MOUSE_DOWN, startDragMe);
		addEventListener (MouseEvent.MOUSE_UP, stopDragMe);
	}
	public function startDragMe (e:MouseEvent):void {
		startDrag ();
	}
	public function stopDragMe (e:MouseEvent):void {
		stopDrag ();
	}
}

/**
 * And now we use a method by Mark Lundin
 * @see https://gist.github.com/658176
 */
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;
class Homography extends Shape {

	public function update (
		p0:Point, p1:Point, p2:Point, p3:Point,
		halfWidth:int = 232, halfHeight:int = 232):void {

		// Find diagonals intersection point
		var pc:Point = new Point;

		var a1:Number = p2.y - p0.y;
		var b1:Number = p0.x - p2.x;
		var a2:Number = p3.y - p1.y;
		var b2:Number = p1.x - p3.x;

		var denom:Number = a1 * b2 - a2 * b1;
		if (denom == 0) {
			// something is better than nothing
			pc.x = 0.25 * (p0.x + p1.x + p2.x + p3.x);
			pc.y = 0.25 * (p0.y + p1.y + p2.y + p3.y);
		} else {
			var c1:Number = p2.x * p0.y - p0.x * p2.y;
			var c2:Number = p3.x * p1.y - p1.x * p3.y;
			pc.x = (b1 * c2 - b2 * c1) / denom;
			pc.y = (a2 * c1 - a1 * c2) / denom;
		}

		p0 = p0.subtract (pc);
		p1 = p1.subtract (pc);
		p2 = p2.subtract (pc);
		p3 = p3.subtract (pc);

		var m:Matrix3D = HomographyUtil.findHomography (
		Vector.<Point> ([
			new Point (-1, -1),
			new Point (1, -1),
			new Point (1, 1),
			new Point (-1, 1)
		]),
		Vector.<Point> ([
			p0, p1, p2, p3
		])
		);

		var v0:Vector3D = m.transformVector (new Vector3D (-1, -1, 1));
		var v1:Vector3D = m.transformVector (new Vector3D (1, -1, 1));
		var v2:Vector3D = m.transformVector (new Vector3D (1, 1, 1));
		var v3:Vector3D = m.transformVector (new Vector3D (-1, 1, 1));

		// find any orthogonal basis in the plane
		var u:Vector3D = new Vector3D (v1.x - v0.x, v1.y - v0.y, v1.z - v0.z);
		var v:Vector3D = new Vector3D (v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
		var scale:Number = 200 / (u.length + v.length);
		var w:Vector3D = u.crossProduct (v); v = w.crossProduct (u);
		u.normalize (); v.normalize ();

		w.x = 0.25 * (v0.x + v1.x + v2.x + v3.x);
		w.y = 0.25 * (v0.y + v1.y + v2.y + v3.y);
		w.z = 0.25 * (v0.z + v1.z + v2.z + v3.z);
		v0 = v0.subtract (w);
		v1 = v1.subtract (w);
		v2 = v2.subtract (w);
		v3 = v3.subtract (w);

		graphics.clear ();
		graphics.beginFill (0xFF0000);
		graphics.drawCircle (
			u.dotProduct (v0) * scale,
			v.dotProduct (v0) * scale,
			5
		);
		1.
		graphics.drawCircle (
			u.dotProduct (v1) * scale,
			v.dotProduct (v1) * scale,
			5
		);
		graphics.drawCircle (
			u.dotProduct (v2) * scale,
			v.dotProduct (v2) * scale,
			5
		);
		graphics.drawCircle (
			u.dotProduct (v3) * scale,
			v.dotProduct (v3) * scale,
			5
		);
	}
}

/**
 * 
 * @author Mark Lundin
 * 
 * Based upon code provided by nicoptere - http://www.nicoptere.net/AS3/homographie/blog/Homography.as
 * The findHomography now computes a Matrix3D that maps the transformation between two sets of complanar points.
 * The transformation finds the a mapping from the source quad to a unit square, 
 * and a second mapping from a unit square to the destination quad.
 * An adjoint is then found for the second matrix and the two multiplied together. 
 * 
 * Standard vectors3d points can be transformed against this matrix. 
 * Divide by the z component to map to a coordinate in the uv plane.
 * 
 */
class HomographyUtil
{

	public static function findHomography( source:Vector.<Point>, destination:Vector.<Point> ):Matrix3D
	{
		/*
		 * This can probably be optimized. Its using a very simple and straightforward equation
		 * 
		 * Mapping is quad -> unit square -> quad. This should probably skip out the unit square and go straight from quad to quad
		 */
		
		var sourceHomography : Matrix3D = HomographyUtil.getSystem( destination );
		var destHomography : Matrix3D 	= HomographyUtil.adjoint( HomographyUtil.getSystem( source ) );
		destHomography.append( sourceHomography );
		
		return destHomography;
		
	}

	public static function getSystem( points:Vector.<Point> ):Matrix3D
	{
		
		var sx:Number = (points[0].x - points[1].x) + (points[2].x - points[3].x);
		var sy:Number = (points[0].y - points[1].y) + (points[2].y - points[3].y);
		
		var dx1:Number = points[1].x - points[2].x;
		var dx2:Number = points[3].x - points[2].x;
		var dy1:Number = points[1].y - points[2].y;
		var dy2:Number = points[3].y - points[2].y;
	 
		var z:Number = (dx1 * dy2) - (dy1 * dx2);
		var g:Number = ((sx * dy2) - (sy * dx2)) / z;
		var h:Number = ((sy * dx1) - (sx * dy1)) / z;
	 
		var a:Number = points[1].x - points[0].x + g * points[1].x;
		var b:Number = points[3].x - points[0].x + h * points[3].x;
		var c:Number = points[0].x;
		var d:Number = points[1].y - points[0].y + g * points[1].y;
		var e:Number = points[3].y - points[0].y + h * points[3].y;	
		var f:Number = points[0].y;
		
		var homography:Vector.<Number> = new Vector.<Number>( 16, true );
		homography[0] = a;	homography[4] = b;	homography[8] = c;	homography[12] = 0;
		homography[1] = d;	homography[5] = e;	homography[9] = f;	homography[13] = 0;
		homography[2] = g;	homography[6] = h;	homography[10] = 1;	homography[14] = 0;
		homography[3] = 0;	homography[7] = 0;	homography[11] = 0;	homography[15] = 0;
		
		return new Matrix3D( homography );
					
	}
	
	public static function adjoint ( matrix : Matrix3D ) : Matrix3D
	{
		
		var adj:Vector.<Number> = new Vector.<Number>( 16, true);
		var m:Vector.<Number> = matrix.rawData;
		
		var a:Number = m[0];
		var b:Number = m[1];
		var c:Number = m[2];
		
		var d:Number = m[4];
		var e:Number = m[5];
		var f:Number = m[6];
		
		var g:Number = m[8];
		var h:Number = m[9];
		
		adj [ 0 ] 	= e-f*h; 	adj [ 4 ] 	= f*g-d; 	adj [ 8 ] 	= d*h-e*g;	adj [ 12 ]	= 0;
		adj [ 1 ] 	= c*h-b; 	adj [ 5 ] 	= a-c*g; 	adj [ 9 ] 	= b*g-a*h;	adj [ 13 ]	= 0;
		adj [ 2 ] 	= b*f-c*e; 	adj [ 6 ] 	= c*d-a*f;	adj [ 10 ] 	= a*e-b*d;	adj [ 14 ]	= 0;
		adj [ 3 ]	= 0;		adj [ 7 ]	= 0;		adj	[ 11 ]	= 0;		adj [ 15 ]	= 1;
		
		return new Matrix3D( adj ); 
		
	}
	
}