Basic 3D vector library.
git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@210 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
@@ -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 + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user