From 79c388a90623f56214495453f45ec9b9bfc38427 Mon Sep 17 00:00:00 2001 From: Robert Zubeck Date: Wed, 25 Apr 2007 23:13:16 +0000 Subject: [PATCH] Basic 3D vector library. git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@210 ed5b42cb-e716-0410-a449-f6a68f950b19 --- src/as/com/threerings/flash/Vector3.as | 138 +++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/as/com/threerings/flash/Vector3.as diff --git a/src/as/com/threerings/flash/Vector3.as b/src/as/com/threerings/flash/Vector3.as new file mode 100644 index 00000000..5cda0b6a --- /dev/null +++ b/src/as/com/threerings/flash/Vector3.as @@ -0,0 +1,138 @@ +package com.threerings.flash { + + +/** + * Basic 3D vector implementation. + */ +public class Vector3 +{ + /** + * Infinite vector - often the result of normalizing a zero vector, or intersecting + * a vector with a parallel plane. + */ + public static const INFINITE :Vector3 = new Vector3(Infinity, Infinity, Infinity); + + /** Vector components. */ + public var x :Number = 0; + public var y :Number = 0; + public var z :Number = 0; + + /** Creates a new vector. All three X, Y, Z parameters are optional. */ + public function Vector3 (x :Number = 0, y :Number = 0, z :Number = 0) + { + this.x = x; + this.y = y; + this.z = z; + } + + /** Duplicates a vector. */ + public function clone() :Vector3 + { + return new Vector3 (this.x, this.y, this.z); + } + + /** Returns this vector's length. */ + public function length () :Number + { + if (this == INFINITE || x == Infinity || y == Infinity || z == Infinity) { + return Infinity; + } else { + return Math.sqrt(x * x + y * y + z * z); + } + } + + /** Returns a new vector that is a normalized version of this vector. */ + public function normalize () :Vector3 + { + var len :Number = length(); + return new Vector3 (x / len, y / len, z / len); + } + + /** Returns the dot product of this vector with vector v. */ + public function dot (v :Vector3) :Number + { + return x * v.x + y * v.y + z * v.z; + } + + /** Returns a new vector that is the cross product of this vector with vector v. */ + public function cross (v :Vector3) :Vector3 + { + return new Vector3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); + } + + /** Returns a new vector that is the summation of this vector with vector v. */ + public function add (v :Vector3) :Vector3 + { + return new Vector3(x + v.x, y + v.y, z + v.z); + } + + /** Returns a new vector that is the subtraction of vector v from this vector.*/ + public function subtract (v :Vector3) :Vector3 + { + return new Vector3(x - v.x, y - v.y, z - v.z); + } + + /** + * Finds the intersection of a ray emitted from s along this vector, + * with a plane passing through point p with normal n. Returns the point + * of intersection, potentially infinite if the ray and plane are parallel. + */ + public function intersection (s :Vector3, p :Vector3, n :Vector3) :Vector3 + { + // formula: given ray from /s/ along vector /this/, and a plane passing + // through /p/ with normal /n/, we find intersection parameter as: + // r = (n dot this) / (n dot (p - s)) + // and the intersection point is: + // s' = s + r * this + var rray :Number = p.subtract(s).dot(n); + var rplane :Number = this.dot(n); + if (rplane == 0) { + return INFINITE; // the two shall never meet + } else { + var r :Number = rray / rplane; + return s.add(this.multiply(r)); + } + } + + /** + * Returns a new vector that is the result of multiplying the current vector + * by the specified scalar. + */ + public function multiply (value :Number) :Vector3 + { + return new Vector3(x * value, y * value, z * value); + } + + /** + * Returns a new vector that is a copy of this vector, with each coordinate clamped + * to within [0, 1]. Please note that this obviously does not preserve the + * vector's original direction in space. + */ + public function clampToUnitBox () :Vector3 + { + return new Vector3(Math.min(Math.max(x, 0), 1), + Math.min(Math.max(y, 0), 1), + Math.min(Math.max(z, 0), 1)); + } + + /** + * Returns a new vector that is the linear interpolation of vectors a and b + * at proportion p, where p is in [0, 1], p = 0 means the result is equal to a, + * and p = 1 means the result is equal to b. + */ + public static function interpolate (a :Vector3, b :Vector3, p :Number) :Vector3 + { + // todo: maybe convert this into a non-static function, to fit the rest of the class? + var q :Number = 1 - p; + return new Vector3(q * a.x + p * b.x, + q * a.y + p * b.y, + q * a.z + p * b.z); + } + + + public function toString () :String + { + return "[" + x + ", " + y + ", " + z + "]"; + } +} +}