phaser/src/math/Vector4.js

540 lines
14 KiB
JavaScript
Raw Normal View History

2018-02-12 16:01:20 +00:00
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
2018-03-20 15:06:30 +00:00
// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji
// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl
var Class = require('../utils/Class');
2018-02-07 15:27:21 +00:00
/**
* @classdesc
* A representation of a vector in 4D space.
*
* A four-component vector.
2018-02-07 15:27:21 +00:00
*
* @class Vector4
2018-10-10 09:49:13 +00:00
* @memberof Phaser.Math
2018-02-07 15:27:21 +00:00
* @constructor
* @since 3.0.0
*
* @param {number} [x] - The x component.
* @param {number} [y] - The y component.
* @param {number} [z] - The z component.
* @param {number} [w] - The w component.
2018-02-07 15:27:21 +00:00
*/
var Vector4 = new Class({
initialize:
function Vector4 (x, y, z, w)
{
2018-02-07 15:27:21 +00:00
/**
* The x component of this Vector.
*
2018-02-22 01:07:30 +00:00
* @name Phaser.Math.Vector4#x
2018-02-07 15:27:21 +00:00
* @type {number}
* @default 0
* @since 3.0.0
*/
this.x = 0;
2018-02-07 15:27:21 +00:00
/**
* The y component of this Vector.
*
2018-02-22 01:07:30 +00:00
* @name Phaser.Math.Vector4#y
2018-02-07 15:27:21 +00:00
* @type {number}
* @default 0
* @since 3.0.0
*/
this.y = 0;
2018-02-07 15:27:21 +00:00
/**
* The z component of this Vector.
*
2018-02-22 01:07:30 +00:00
* @name Phaser.Math.Vector4#z
2018-02-07 15:27:21 +00:00
* @type {number}
* @default 0
* @since 3.0.0
*/
this.z = 0;
2018-02-07 15:27:21 +00:00
/**
* The w component of this Vector.
*
2018-02-22 01:07:30 +00:00
* @name Phaser.Math.Vector4#w
2018-02-07 15:27:21 +00:00
* @type {number}
* @default 0
* @since 3.0.0
*/
this.w = 0;
2018-02-07 15:27:21 +00:00
if (typeof x === 'object')
{
this.x = x.x || 0;
this.y = x.y || 0;
this.z = x.z || 0;
this.w = x.w || 0;
}
else
{
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = w || 0;
}
},
2018-01-26 06:19:27 +00:00
/**
* Make a clone of this Vector4.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#clone
* @since 3.0.0
*
* @return {Phaser.Math.Vector4} A clone of this Vector4.
2018-01-26 06:19:27 +00:00
*/
clone: function ()
{
return new Vector4(this.x, this.y, this.z, this.w);
},
2018-01-26 06:19:27 +00:00
/**
* Copy the components of a given Vector into this Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#copy
* @since 3.0.0
*
* @param {Phaser.Math.Vector4} src - The Vector to copy the components from.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
copy: function (src)
{
this.x = src.x;
this.y = src.y;
this.z = src.z || 0;
this.w = src.w || 0;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Check whether this Vector is equal to a given Vector.
*
* Performs a strict quality check against each Vector's components.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#equals
* @since 3.0.0
*
2018-09-28 10:04:19 +00:00
* @param {Phaser.Math.Vector4} v - The vector to check equality with.
2018-01-26 06:19:27 +00:00
*
2018-09-28 10:04:19 +00:00
* @return {boolean} A boolean indicating whether the two Vectors are equal or not.
2018-01-26 06:19:27 +00:00
*/
2017-09-21 16:11:56 +00:00
equals: function (v)
{
return ((this.x === v.x) && (this.y === v.y) && (this.z === v.z) && (this.w === v.w));
},
2018-01-26 06:19:27 +00:00
/**
* Set the `x`, `y`, `z` and `w` components of the this Vector to the given `x`, `y`, `z` and `w` values.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#set
* @since 3.0.0
*
* @param {(number|object)} x - The x value to set for this Vector, or an object containing x, y, z and w components.
* @param {number} y - The y value to set for this Vector.
* @param {number} z - The z value to set for this Vector.
* @param {number} w - The z value to set for this Vector.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
set: function (x, y, z, w)
{
if (typeof x === 'object')
{
this.x = x.x || 0;
this.y = x.y || 0;
this.z = x.z || 0;
this.w = x.w || 0;
}
else
{
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = w || 0;
}
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Add a given Vector to this Vector. Addition is component-wise.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#add
* @since 3.0.0
*
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to add to this Vector.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
add: function (v)
{
this.x += v.x;
this.y += v.y;
this.z += v.z || 0;
this.w += v.w || 0;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Subtract the given Vector from this Vector. Subtraction is component-wise.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#subtract
* @since 3.0.0
*
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to subtract from this Vector.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
subtract: function (v)
{
this.x -= v.x;
this.y -= v.y;
this.z -= v.z || 0;
this.w -= v.w || 0;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Scale this Vector by the given value.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#scale
* @since 3.0.0
*
* @param {number} scale - The value to scale this Vector by.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
scale: function (scale)
{
this.x *= scale;
this.y *= scale;
this.z *= scale;
this.w *= scale;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Calculate the length (or magnitude) of this Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#length
* @since 3.0.0
*
* @return {number} The length of this Vector.
2018-01-26 06:19:27 +00:00
*/
length: function ()
{
var x = this.x;
var y = this.y;
var z = this.z;
var w = this.w;
return Math.sqrt(x * x + y * y + z * z + w * w);
},
2018-01-26 06:19:27 +00:00
/**
* Calculate the length of this Vector squared.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#lengthSq
* @since 3.0.0
*
* @return {number} The length of this Vector, squared.
2018-01-26 06:19:27 +00:00
*/
lengthSq: function ()
{
var x = this.x;
var y = this.y;
var z = this.z;
var w = this.w;
return x * x + y * y + z * z + w * w;
},
2018-01-26 06:19:27 +00:00
/**
* Normalize this Vector.
*
* Makes the vector a unit length vector (magnitude of 1) in the same direction.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#normalize
* @since 3.0.0
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
normalize: function ()
{
var x = this.x;
var y = this.y;
var z = this.z;
var w = this.w;
var len = x * x + y * y + z * z + w * w;
if (len > 0)
{
len = 1 / Math.sqrt(len);
this.x = x * len;
this.y = y * len;
this.z = z * len;
this.w = w * len;
}
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Calculate the dot product of this Vector and the given Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#dot
* @since 3.0.0
*
* @param {Phaser.Math.Vector4} v - The Vector4 to dot product with this Vector4.
2018-01-26 06:19:27 +00:00
*
* @return {number} The dot product of this Vector and the given Vector.
2018-01-26 06:19:27 +00:00
*/
dot: function (v)
{
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
},
2018-01-26 06:19:27 +00:00
/**
* Linearly interpolate between this Vector and the given Vector.
*
* Interpolates this Vector towards the given Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#lerp
* @since 3.0.0
*
* @param {Phaser.Math.Vector4} v - The Vector4 to interpolate towards.
* @param {number} [t=0] - The interpolation percentage, between 0 and 1.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
lerp: function (v, t)
{
if (t === undefined) { t = 0; }
var ax = this.x;
var ay = this.y;
var az = this.z;
var aw = this.w;
this.x = ax + t * (v.x - ax);
this.y = ay + t * (v.y - ay);
this.z = az + t * (v.z - az);
this.w = aw + t * (v.w - aw);
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Perform a component-wise multiplication between this Vector and the given Vector.
*
* Multiplies this Vector by the given Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#multiply
* @since 3.0.0
*
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to multiply this Vector by.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
multiply: function (v)
{
this.x *= v.x;
this.y *= v.y;
this.z *= v.z || 1;
this.w *= v.w || 1;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Perform a component-wise division between this Vector and the given Vector.
*
* Divides this Vector by the given Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#divide
* @since 3.0.0
*
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to divide this Vector by.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
divide: function (v)
{
this.x /= v.x;
this.y /= v.y;
this.z /= v.z || 1;
this.w /= v.w || 1;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Calculate the distance between this Vector and the given Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#distance
* @since 3.0.0
*
2018-09-28 10:04:19 +00:00
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to calculate the distance to.
2018-01-26 06:19:27 +00:00
*
* @return {number} The distance from this Vector to the given Vector.
2018-01-26 06:19:27 +00:00
*/
distance: function (v)
{
var dx = v.x - this.x;
var dy = v.y - this.y;
var dz = v.z - this.z || 0;
var dw = v.w - this.w || 0;
return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
},
2018-01-26 06:19:27 +00:00
/**
* Calculate the distance between this Vector and the given Vector, squared.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#distanceSq
* @since 3.0.0
*
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to calculate the distance to.
2018-01-26 06:19:27 +00:00
*
* @return {number} The distance from this Vector to the given Vector, squared.
2018-01-26 06:19:27 +00:00
*/
distanceSq: function (v)
{
var dx = v.x - this.x;
var dy = v.y - this.y;
var dz = v.z - this.z || 0;
var dw = v.w - this.w || 0;
return dx * dx + dy * dy + dz * dz + dw * dw;
},
2018-01-26 06:19:27 +00:00
/**
* Negate the `x`, `y`, `z` and `w` components of this Vector.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#negate
* @since 3.0.0
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
negate: function ()
{
this.x = -this.x;
this.y = -this.y;
this.z = -this.z;
this.w = -this.w;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Transform this Vector with the given Matrix.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#transformMat4
* @since 3.0.0
*
* @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector4 with.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
transformMat4: function (mat)
{
var x = this.x;
var y = this.y;
var z = this.z;
var w = this.w;
var m = mat.val;
this.x = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
this.y = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
this.z = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
this.w = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Transform this Vector with the given Quaternion.
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#transformQuat
* @since 3.0.0
*
* @param {Phaser.Math.Quaternion} q - The Quaternion to transform this Vector with.
2018-01-26 06:19:27 +00:00
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
transformQuat: function (q)
{
// TODO: is this really the same as Vector3?
// Also, what about this: http://molecularmusings.wordpress.com/2013/05/24/a-faster-quaternion-vector-multiplication/
// benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
var x = this.x;
var y = this.y;
var z = this.z;
var qx = q.x;
var qy = q.y;
var qz = q.z;
var qw = q.w;
// calculate quat * vec
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return this;
},
2018-01-26 06:19:27 +00:00
/**
* Make this Vector the zero vector (0, 0, 0, 0).
2018-01-26 06:19:27 +00:00
*
* @method Phaser.Math.Vector4#reset
* @since 3.0.0
*
* @return {Phaser.Math.Vector4} This Vector4.
2018-01-26 06:19:27 +00:00
*/
reset: function ()
{
this.x = 0;
this.y = 0;
this.z = 0;
this.w = 0;
return this;
}
});
2018-02-22 01:07:30 +00:00
// TODO: Check if these are required internally, if not, remove.
2017-09-15 15:46:04 +00:00
Vector4.prototype.sub = Vector4.prototype.subtract;
Vector4.prototype.mul = Vector4.prototype.multiply;
Vector4.prototype.div = Vector4.prototype.divide;
Vector4.prototype.dist = Vector4.prototype.distance;
Vector4.prototype.distSq = Vector4.prototype.distanceSq;
Vector4.prototype.len = Vector4.prototype.length;
Vector4.prototype.lenSq = Vector4.prototype.lengthSq;
module.exports = Vector4;