slerp test

by makc3d
♥0 | Line 82 | Modified 2011-12-05 03:13:48 | 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/oaoF
 */

package {
	import com.actionscriptbible.Example;
	
	/**
	 * slerp test
	 */
	public class SlerpTest extends Example {
		
		public function SlerpTest () {
			var a:Vertex = new Vertex;
			a.x = 1; a.y = 0; a.z = 0;
			var b:Vertex = new Vertex;
			b.x = 3; b.y = 0; b.z = 0;
			var c:Vertex = a.interpolate (b, 0.5);
			trace (c.x, c.y, c.z); // 2,0,0

			b.x = -3;
			c = a.interpolate (b, 0.5);
			trace (c.x, c.y, c.z); // 0,?,? (length = 2)

			b.x = 0; b.y = 1;
			c = a.interpolate (b, 0.5);
			trace (c.x, c.y, c.z); // .7071,.7071,0

			c = a.interpolate (b, 1.0);
			trace (c.x, c.y, c.z); // 0,1,0
		}
	}
}

class Vertex {
	public var x:Number;
	public var y:Number;
	public var z:Number;

	public function interpolate (other:Vertex, t:Number):Vertex {
		var v:Vertex = new Vertex;
		slerp (this.x, this.y, this.z, other.x, other.y, other.z, t);
		v.x = sx; v.y = sy; v.z = sz;
		return v;
	}

	private var cx:Number;
	private var cy:Number;
	private var cz:Number;
	private function cross (x1:Number, y1:Number, z1:Number, x2:Number, y2:Number, z2:Number):void {
		cx = y1 * z2 - z1 * y2;
		cy = z1 * x2 - x1 * z2;
		cz = x1 * y2 - y1 * x2;
	}

	private var sx:Number;
	private var sy:Number;
	private var sz:Number;
	private function slerp (x1:Number, y1:Number, z1:Number, x2:Number, y2:Number, z2:Number, t:Number):void {
		// projection plane
		var ax:Number, ay:Number, az:Number, bx:Number, by:Number, bz:Number;
		cross (x1, y1, z1, x2, y2, z2);
		var d:Number = cx * cx + cy * cy + cz * cz;
		if (d == 0) {
			ax = 1; ay = 0; az = 0;
			if ((x1 != 0) || (y1 != 0)) {
				bx = 0; by = 1; bz = 0;
			} else {
				bx = 0; by = 0; bz = 1;
			}
		} else {
			if ((cx != 0) || (cy != 0)) {
				ax = -cy; ay = +cx; az = 0;
			} else {
				ax = -cz; ay = 0; az = +cx;
			}
			cross (cx, cy, cz, ax, ay, az);
			bx = cx; by = cy; bz = cz;
		}

		// lengths
		var La:Number = Math.sqrt (ax * ax + ay * ay + az * az);
		var Lb:Number = Math.sqrt (bx * bx + by * by + bz * bz);

		// projection
		var a1:Number = (ax * x1 + ay * y1 + az * z1) / La;
		var b1:Number = (bx * x1 + by * y1 + bz * z1) / Lb;
		var a2:Number = (ax * x2 + ay * y2 + az * z2) / La;
		var b2:Number = (bx * x2 + by * y2 + bz * z2) / Lb;

		// lengths (should be mostly equal)
		var L1:Number = Math.sqrt (a1 * a1 + b1 * b1);
		var L2:Number = Math.sqrt (a2 * a2 + b2 * b2);

		// angles
		var p1:Number = Math.atan2 (a1, b1); if (p1 < 0) p1 += 2 * Math.PI;
		var p2:Number = Math.atan2 (a2, b2); if (p2 < 0) p2 += 2 * Math.PI;

		// interpolate
		var pt:Number = p1 * (1 - t) + p2 * t;
		d = p1 - p2; if ((d > Math.PI) || (d < -Math.PI)) pt += Math.PI;

		var Lt:Number = L1 * (1 - t) + L2 * t;

		// back to vector, 2D
		var at:Number = Lt * Math.sin (pt);
		var bt:Number = Lt * Math.cos (pt);

		// finally, 3D
		sx = ax * at + bx * bt;
		sy = ay * at + by * bt;
		sz = az * at + bz * bt;
	}
}