@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
1,295 lines (1,294 loc) • 305 kB
JavaScript
/* eslint-disable @typescript-eslint/naming-convention */
import { Epsilon } from "./math.constants.js";
import { BuildTuple } from "../Misc/arrayTools.js";
import { RegisterClass } from "../Misc/typeStore.js";
import { PerformanceConfigurator } from "../Engines/performanceConfigurator.js";
import { EngineStore } from "../Engines/engineStore.js";
import { Clamp, Lerp, NormalizeRadians, RandomRange, WithinEpsilon } from "./math.scalar.functions.js";
import { CopyMatrixToArray, InvertMatrixToArray, MatrixManagement, MultiplyMatricesToArray } from "./ThinMaths/thinMath.matrix.functions.js";
// eslint-disable-next-line @typescript-eslint/naming-convention
const ExtractAsInt = (value) => {
return parseInt(value.toString().replace(/\W/g, ""));
};
/**
* Class representing a vector containing 2 coordinates
* Example Playground - Overview - https://playground.babylonjs.com/#QYBWV4#9
*/
export class Vector2 {
/**
* Creates a new Vector2 from the given x and y coordinates
* @param x defines the first coordinate
* @param y defines the second coordinate
*/
constructor(
/** [0] defines the first coordinate */
x = 0,
/** [0] defines the second coordinate */
y = 0) {
this.x = x;
this.y = y;
}
/**
* Gets a string with the Vector2 coordinates
* @returns a string with the Vector2 coordinates
*/
toString() {
return `{X: ${this.x} Y: ${this.y}}`;
}
/**
* Gets class name
* @returns the string "Vector2"
*/
getClassName() {
return "Vector2";
}
/**
* Gets current vector hash code
* @returns the Vector2 hash code as a number
*/
getHashCode() {
const x = ExtractAsInt(this.x);
const y = ExtractAsInt(this.y);
let hash = x;
hash = (hash * 397) ^ y;
return hash;
}
// Operators
/**
* Sets the Vector2 coordinates in the given array or Float32Array from the given index.
* Example Playground https://playground.babylonjs.com/#QYBWV4#15
* @param array defines the source array
* @param index defines the offset in source array
* @returns the current Vector2
*/
toArray(array, index = 0) {
array[index] = this.x;
array[index + 1] = this.y;
return this;
}
/**
* Update the current vector from an array
* Example Playground https://playground.babylonjs.com/#QYBWV4#39
* @param array defines the destination array
* @param offset defines the offset in the destination array
* @returns the current Vector2
*/
fromArray(array, offset = 0) {
Vector2.FromArrayToRef(array, offset, this);
return this;
}
/**
* Copy the current vector to an array
* Example Playground https://playground.babylonjs.com/#QYBWV4#40
* @returns a new array with 2 elements: the Vector2 coordinates.
*/
asArray() {
return [this.x, this.y];
}
/**
* Sets the Vector2 coordinates with the given Vector2 coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#24
* @param source defines the source Vector2
* @returns the current updated Vector2
*/
copyFrom(source) {
this.x = source.x;
this.y = source.y;
return this;
}
/**
* Sets the Vector2 coordinates with the given floats
* Example Playground https://playground.babylonjs.com/#QYBWV4#25
* @param x defines the first coordinate
* @param y defines the second coordinate
* @returns the current updated Vector2
*/
copyFromFloats(x, y) {
this.x = x;
this.y = y;
return this;
}
/**
* Sets the Vector2 coordinates with the given floats
* Example Playground https://playground.babylonjs.com/#QYBWV4#62
* @param x defines the first coordinate
* @param y defines the second coordinate
* @returns the current updated Vector2
*/
set(x, y) {
return this.copyFromFloats(x, y);
}
/**
* Copies the given float to the current Vector2 coordinates
* @param v defines the x and y coordinates of the operand
* @returns the current updated Vector2
*/
setAll(v) {
return this.copyFromFloats(v, v);
}
/**
* Add another vector with the current one
* Example Playground https://playground.babylonjs.com/#QYBWV4#11
* @param otherVector defines the other vector
* @returns a new Vector2 set with the addition of the current Vector2 and the given one coordinates
*/
add(otherVector) {
return new Vector2(this.x + otherVector.x, this.y + otherVector.y);
}
/**
* Sets the "result" coordinates with the addition of the current Vector2 and the given one coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#12
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns result input
*/
addToRef(otherVector, result) {
result.x = this.x + otherVector.x;
result.y = this.y + otherVector.y;
return result;
}
/**
* Set the Vector2 coordinates by adding the given Vector2 coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#13
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
addInPlace(otherVector) {
this.x += otherVector.x;
this.y += otherVector.y;
return this;
}
/**
* Adds the given coordinates to the current Vector2
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @returns the current updated Vector2
*/
addInPlaceFromFloats(x, y) {
this.x += x;
this.y += y;
return this;
}
/**
* Gets a new Vector2 by adding the current Vector2 coordinates to the given Vector3 x, y coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#14
* @param otherVector defines the other vector
* @returns a new Vector2
*/
addVector3(otherVector) {
return new Vector2(this.x + otherVector.x, this.y + otherVector.y);
}
/**
* Gets a new Vector2 set with the subtracted coordinates of the given one from the current Vector2
* Example Playground https://playground.babylonjs.com/#QYBWV4#61
* @param otherVector defines the other vector
* @returns a new Vector2
*/
subtract(otherVector) {
return new Vector2(this.x - otherVector.x, this.y - otherVector.y);
}
/**
* Sets the "result" coordinates with the subtraction of the given one from the current Vector2 coordinates.
* Example Playground https://playground.babylonjs.com/#QYBWV4#63
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns result input
*/
subtractToRef(otherVector, result) {
result.x = this.x - otherVector.x;
result.y = this.y - otherVector.y;
return result;
}
/**
* Sets the current Vector2 coordinates by subtracting from it the given one coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#88
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
subtractInPlace(otherVector) {
this.x -= otherVector.x;
this.y -= otherVector.y;
return this;
}
/**
* Multiplies in place the current Vector2 coordinates by the given ones
* Example Playground https://playground.babylonjs.com/#QYBWV4#43
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
multiplyInPlace(otherVector) {
this.x *= otherVector.x;
this.y *= otherVector.y;
return this;
}
/**
* Returns a new Vector2 set with the multiplication of the current Vector2 and the given one coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#42
* @param otherVector defines the other vector
* @returns a new Vector2
*/
multiply(otherVector) {
return new Vector2(this.x * otherVector.x, this.y * otherVector.y);
}
/**
* Sets "result" coordinates with the multiplication of the current Vector2 and the given one coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#44
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns result input
*/
multiplyToRef(otherVector, result) {
result.x = this.x * otherVector.x;
result.y = this.y * otherVector.y;
return result;
}
/**
* Gets a new Vector2 set with the Vector2 coordinates multiplied by the given floats
* Example Playground https://playground.babylonjs.com/#QYBWV4#89
* @param x defines the first coordinate
* @param y defines the second coordinate
* @returns a new Vector2
*/
multiplyByFloats(x, y) {
return new Vector2(this.x * x, this.y * y);
}
/**
* Returns a new Vector2 set with the Vector2 coordinates divided by the given one coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#27
* @param otherVector defines the other vector
* @returns a new Vector2
*/
divide(otherVector) {
return new Vector2(this.x / otherVector.x, this.y / otherVector.y);
}
/**
* Sets the "result" coordinates with the Vector2 divided by the given one coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#30
* @param otherVector defines the other vector
* @param result defines the target vector
* @returns result input
*/
divideToRef(otherVector, result) {
result.x = this.x / otherVector.x;
result.y = this.y / otherVector.y;
return result;
}
/**
* Divides the current Vector2 coordinates by the given ones
* Example Playground https://playground.babylonjs.com/#QYBWV4#28
* @param otherVector defines the other vector
* @returns the current updated Vector2
*/
divideInPlace(otherVector) {
this.x = this.x / otherVector.x;
this.y = this.y / otherVector.y;
return this;
}
/**
* Updates the current Vector2 with the minimal coordinate values between its and the given vector ones
* @param other defines the second operand
* @returns the current updated Vector2
*/
minimizeInPlace(other) {
return this.minimizeInPlaceFromFloats(other.x, other.y);
}
/**
* Updates the current Vector2 with the maximal coordinate values between its and the given vector ones.
* @param other defines the second operand
* @returns the current updated Vector2
*/
maximizeInPlace(other) {
return this.maximizeInPlaceFromFloats(other.x, other.y);
}
/**
* Updates the current Vector2 with the minimal coordinate values between its and the given coordinates
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @returns the current updated Vector2
*/
minimizeInPlaceFromFloats(x, y) {
this.x = Math.min(x, this.x);
this.y = Math.min(y, this.y);
return this;
}
/**
* Updates the current Vector2 with the maximal coordinate values between its and the given coordinates.
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @returns the current updated Vector2
*/
maximizeInPlaceFromFloats(x, y) {
this.x = Math.max(x, this.x);
this.y = Math.max(y, this.y);
return this;
}
/**
* Returns a new Vector2 set with the subtraction of the given floats from the current Vector2 coordinates
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @returns the resulting Vector2
*/
subtractFromFloats(x, y) {
return new Vector2(this.x - x, this.y - y);
}
/**
* Subtracts the given floats from the current Vector2 coordinates and set the given vector "result" with this result
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param result defines the Vector2 object where to store the result
* @returns the result
*/
subtractFromFloatsToRef(x, y, result) {
result.x = this.x - x;
result.y = this.y - y;
return result;
}
/**
* Gets a new Vector2 with current Vector2 negated coordinates
* @returns a new Vector2
*/
negate() {
return new Vector2(-this.x, -this.y);
}
/**
* Negate this vector in place
* Example Playground https://playground.babylonjs.com/#QYBWV4#23
* @returns this
*/
negateInPlace() {
this.x *= -1;
this.y *= -1;
return this;
}
/**
* Negate the current Vector2 and stores the result in the given vector "result" coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#41
* @param result defines the Vector3 object where to store the result
* @returns the result
*/
negateToRef(result) {
result.x = -this.x;
result.y = -this.y;
return result;
}
/**
* Multiply the Vector2 coordinates by
* Example Playground https://playground.babylonjs.com/#QYBWV4#59
* @param scale defines the scaling factor
* @returns the current updated Vector2
*/
scaleInPlace(scale) {
this.x *= scale;
this.y *= scale;
return this;
}
/**
* Returns a new Vector2 scaled by "scale" from the current Vector2
* Example Playground https://playground.babylonjs.com/#QYBWV4#52
* @param scale defines the scaling factor
* @returns a new Vector2
*/
scale(scale) {
return new Vector2(this.x * scale, this.y * scale);
}
/**
* Scale the current Vector2 values by a factor to a given Vector2
* Example Playground https://playground.babylonjs.com/#QYBWV4#57
* @param scale defines the scale factor
* @param result defines the Vector2 object where to store the result
* @returns result input
*/
scaleToRef(scale, result) {
result.x = this.x * scale;
result.y = this.y * scale;
return result;
}
/**
* Scale the current Vector2 values by a factor and add the result to a given Vector2
* Example Playground https://playground.babylonjs.com/#QYBWV4#58
* @param scale defines the scale factor
* @param result defines the Vector2 object where to store the result
* @returns result input
*/
scaleAndAddToRef(scale, result) {
result.x += this.x * scale;
result.y += this.y * scale;
return result;
}
/**
* Gets a boolean if two vectors are equals
* Example Playground https://playground.babylonjs.com/#QYBWV4#31
* @param otherVector defines the other vector
* @returns true if the given vector coordinates strictly equal the current Vector2 ones
*/
equals(otherVector) {
return otherVector && this.x === otherVector.x && this.y === otherVector.y;
}
/**
* Gets a boolean if two vectors are equals (using an epsilon value)
* Example Playground https://playground.babylonjs.com/#QYBWV4#32
* @param otherVector defines the other vector
* @param epsilon defines the minimal distance to consider equality
* @returns true if the given vector coordinates are close to the current ones by a distance of epsilon.
*/
equalsWithEpsilon(otherVector, epsilon = Epsilon) {
return otherVector && WithinEpsilon(this.x, otherVector.x, epsilon) && WithinEpsilon(this.y, otherVector.y, epsilon);
}
/**
* Returns true if the current Vector2 coordinates equals the given floats
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @returns true if both vectors are equal
*/
equalsToFloats(x, y) {
return this.x === x && this.y === y;
}
/**
* Gets a new Vector2 from current Vector2 floored values
* Example Playground https://playground.babylonjs.com/#QYBWV4#35
* eg (1.2, 2.31) returns (1, 2)
* @returns a new Vector2
*/
floor() {
return new Vector2(Math.floor(this.x), Math.floor(this.y));
}
/**
* Gets the current Vector2's floored values and stores them in result
* @param result the Vector2 to store the result in
* @returns the result Vector2
*/
floorToRef(result) {
result.x = Math.floor(this.x);
result.y = Math.floor(this.y);
return result;
}
/**
* Gets a new Vector2 from current Vector2 fractional values
* Example Playground https://playground.babylonjs.com/#QYBWV4#34
* eg (1.2, 2.31) returns (0.2, 0.31)
* @returns a new Vector2
*/
fract() {
return new Vector2(this.x - Math.floor(this.x), this.y - Math.floor(this.y));
}
/**
* Gets the current Vector2's fractional values and stores them in result
* @param result the Vector2 to store the result in
* @returns the result Vector2
*/
fractToRef(result) {
result.x = this.x - Math.floor(this.x);
result.y = this.y - Math.floor(this.y);
return result;
}
/**
* Gets a new Vector2 rotated by the given angle
* @param angle defines the rotation angle
* @returns a new Vector2
*/
rotate(angle) {
return this.rotateToRef(angle, new Vector2());
}
/**
* Rotate the current vector into a given result vector
* Example Playground https://playground.babylonjs.com/#QYBWV4#49
* @param angle defines the rotation angle
* @param result defines the result vector where to store the rotated vector
* @returns result input
*/
rotateToRef(angle, result) {
const cos = Math.cos(angle);
const sin = Math.sin(angle);
result.x = cos * this.x - sin * this.y;
result.y = sin * this.x + cos * this.y;
return result;
}
// Properties
/**
* Gets the length of the vector
* @returns the vector length (float)
*/
length() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
/**
* Gets the vector squared length
* @returns the vector squared length (float)
*/
lengthSquared() {
return this.x * this.x + this.y * this.y;
}
// Methods
/**
* Normalize the vector
* Example Playground https://playground.babylonjs.com/#QYBWV4#48
* @returns the current updated Vector2
*/
normalize() {
return this.normalizeFromLength(this.length());
}
/**
* Normalize the current Vector2 with the given input length.
* Please note that this is an in place operation.
* @param len the length of the vector
* @returns the current updated Vector2
*/
normalizeFromLength(len) {
if (len === 0 || len === 1.0) {
return this;
}
return this.scaleInPlace(1.0 / len);
}
/**
* Normalize the current Vector2 to a new vector
* @returns the new Vector2
*/
normalizeToNew() {
const normalized = new Vector2();
this.normalizeToRef(normalized);
return normalized;
}
/**
* Normalize the current Vector2 to the reference
* @param result define the Vector to update
* @returns the updated Vector2
*/
normalizeToRef(result) {
const len = this.length();
if (len === 0) {
result.x = this.x;
result.y = this.y;
}
return this.scaleToRef(1.0 / len, result);
}
/**
* Gets a new Vector2 copied from the Vector2
* Example Playground https://playground.babylonjs.com/#QYBWV4#20
* @returns a new Vector2
*/
clone() {
return new Vector2(this.x, this.y);
}
/**
* Gets the dot product of the current vector and the vector "otherVector"
* @param otherVector defines second vector
* @returns the dot product (float)
*/
dot(otherVector) {
return this.x * otherVector.x + this.y * otherVector.y;
}
// Statics
/**
* Gets a new Vector2(0, 0)
* @returns a new Vector2
*/
static Zero() {
return new Vector2(0, 0);
}
/**
* Gets a new Vector2(1, 1)
* @returns a new Vector2
*/
static One() {
return new Vector2(1, 1);
}
/**
* Returns a new Vector2 with random values between min and max
* @param min the minimum random value
* @param max the maximum random value
* @returns a Vector2 with random values between min and max
*/
static Random(min = 0, max = 1) {
return new Vector2(RandomRange(min, max), RandomRange(min, max));
}
/**
* Sets a Vector2 with random values between min and max
* @param min the minimum random value
* @param max the maximum random value
* @param ref the ref to store the values in
* @returns the ref with random values between min and max
*/
static RandomToRef(min = 0, max = 1, ref) {
return ref.copyFromFloats(RandomRange(min, max), RandomRange(min, max));
}
/**
* Gets a zero Vector2 that must not be updated
*/
static get ZeroReadOnly() {
return Vector2._ZeroReadOnly;
}
/**
* Gets a new Vector2 set from the given index element of the given array
* Example Playground https://playground.babylonjs.com/#QYBWV4#79
* @param array defines the data source
* @param offset defines the offset in the data source
* @returns a new Vector2
*/
static FromArray(array, offset = 0) {
return new Vector2(array[offset], array[offset + 1]);
}
/**
* Sets "result" from the given index element of the given array
* Example Playground https://playground.babylonjs.com/#QYBWV4#80
* @param array defines the data source
* @param offset defines the offset in the data source
* @param result defines the target vector
* @returns result input
*/
static FromArrayToRef(array, offset, result) {
result.x = array[offset];
result.y = array[offset + 1];
return result;
}
/**
* Sets the given vector "result" with the given floats.
* @param x defines the x coordinate of the source
* @param y defines the y coordinate of the source
* @param result defines the Vector2 where to store the result
* @returns the result vector
*/
static FromFloatsToRef(x, y, result) {
result.copyFromFloats(x, y);
return result;
}
/**
* Gets a new Vector2 located for "amount" (float) on the CatmullRom spline defined by the given four Vector2
* Example Playground https://playground.babylonjs.com/#QYBWV4#65
* @param value1 defines 1st point of control
* @param value2 defines 2nd point of control
* @param value3 defines 3rd point of control
* @param value4 defines 4th point of control
* @param amount defines the interpolation factor
* @returns a new Vector2
*/
static CatmullRom(value1, value2, value3, value4, amount) {
const squared = amount * amount;
const cubed = amount * squared;
const x = 0.5 *
(2.0 * value2.x +
(-value1.x + value3.x) * amount +
(2.0 * value1.x - 5.0 * value2.x + 4.0 * value3.x - value4.x) * squared +
(-value1.x + 3.0 * value2.x - 3.0 * value3.x + value4.x) * cubed);
const y = 0.5 *
(2.0 * value2.y +
(-value1.y + value3.y) * amount +
(2.0 * value1.y - 5.0 * value2.y + 4.0 * value3.y - value4.y) * squared +
(-value1.y + 3.0 * value2.y - 3.0 * value3.y + value4.y) * cubed);
return new Vector2(x, y);
}
/**
* Sets reference with same the coordinates than "value" ones if the vector "value" is in the square defined by "min" and "max".
* If a coordinate of "value" is lower than "min" coordinates, the returned Vector2 is given this "min" coordinate.
* If a coordinate of "value" is greater than "max" coordinates, the returned Vector2 is given this "max" coordinate
* @param value defines the value to clamp
* @param min defines the lower limit
* @param max defines the upper limit
* @param ref the reference
* @returns the reference
*/
static ClampToRef(value, min, max, ref) {
ref.x = Clamp(value.x, min.x, max.x);
ref.y = Clamp(value.y, min.y, max.y);
return ref;
}
/**
* Returns a new Vector2 set with same the coordinates than "value" ones if the vector "value" is in the square defined by "min" and "max".
* If a coordinate of "value" is lower than "min" coordinates, the returned Vector2 is given this "min" coordinate.
* If a coordinate of "value" is greater than "max" coordinates, the returned Vector2 is given this "max" coordinate
* Example Playground https://playground.babylonjs.com/#QYBWV4#76
* @param value defines the value to clamp
* @param min defines the lower limit
* @param max defines the upper limit
* @returns a new Vector2
*/
static Clamp(value, min, max) {
const x = Clamp(value.x, min.x, max.x);
const y = Clamp(value.y, min.y, max.y);
return new Vector2(x, y);
}
/**
* Returns a new Vector2 located for "amount" (float) on the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2"
* Example Playground https://playground.babylonjs.com/#QYBWV4#81
* @param value1 defines the 1st control point
* @param tangent1 defines the outgoing tangent
* @param value2 defines the 2nd control point
* @param tangent2 defines the incoming tangent
* @param amount defines the interpolation factor
* @returns a new Vector2
*/
static Hermite(value1, tangent1, value2, tangent2, amount) {
const squared = amount * amount;
const cubed = amount * squared;
const part1 = 2.0 * cubed - 3.0 * squared + 1.0;
const part2 = -2.0 * cubed + 3.0 * squared;
const part3 = cubed - 2.0 * squared + amount;
const part4 = cubed - squared;
const x = value1.x * part1 + value2.x * part2 + tangent1.x * part3 + tangent2.x * part4;
const y = value1.y * part1 + value2.y * part2 + tangent1.y * part3 + tangent2.y * part4;
return new Vector2(x, y);
}
/**
* Returns a new Vector2 which is the 1st derivative of the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2".
* Example Playground https://playground.babylonjs.com/#QYBWV4#82
* @param value1 defines the first control point
* @param tangent1 defines the first tangent
* @param value2 defines the second control point
* @param tangent2 defines the second tangent
* @param time define where the derivative must be done
* @returns 1st derivative
*/
static Hermite1stDerivative(value1, tangent1, value2, tangent2, time) {
return this.Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, new Vector2());
}
/**
* Returns a new Vector2 which is the 1st derivative of the Hermite spline defined by the vectors "value1", "value2", "tangent1", "tangent2".
* Example Playground https://playground.babylonjs.com/#QYBWV4#83
* @param value1 defines the first control point
* @param tangent1 defines the first tangent
* @param value2 defines the second control point
* @param tangent2 defines the second tangent
* @param time define where the derivative must be done
* @param result define where the derivative will be stored
* @returns result input
*/
static Hermite1stDerivativeToRef(value1, tangent1, value2, tangent2, time, result) {
const t2 = time * time;
result.x = (t2 - time) * 6 * value1.x + (3 * t2 - 4 * time + 1) * tangent1.x + (-t2 + time) * 6 * value2.x + (3 * t2 - 2 * time) * tangent2.x;
result.y = (t2 - time) * 6 * value1.y + (3 * t2 - 4 * time + 1) * tangent1.y + (-t2 + time) * 6 * value2.y + (3 * t2 - 2 * time) * tangent2.y;
return result;
}
/**
* Returns a new Vector2 located for "amount" (float) on the linear interpolation between the vector "start" adn the vector "end".
* Example Playground https://playground.babylonjs.com/#QYBWV4#84
* @param start defines the start vector
* @param end defines the end vector
* @param amount defines the interpolation factor
* @returns a new Vector2
*/
static Lerp(start, end, amount) {
return Vector2.LerpToRef(start, end, amount, new Vector2());
}
/**
* Sets the given vector "result" with the result of the linear interpolation from the vector "start" for "amount" to the vector "end"
* @param start defines the start value
* @param end defines the end value
* @param amount max defines amount between both (between 0 and 1)
* @param result defines the Vector2 where to store the result
* @returns result input
*/
static LerpToRef(start, end, amount, result) {
result.x = start.x + (end.x - start.x) * amount;
result.y = start.y + (end.y - start.y) * amount;
return result;
}
/**
* Gets the dot product of the vector "left" and the vector "right"
* Example Playground https://playground.babylonjs.com/#QYBWV4#90
* @param left defines first vector
* @param right defines second vector
* @returns the dot product (float)
*/
static Dot(left, right) {
return left.x * right.x + left.y * right.y;
}
/**
* Returns a new Vector2 equal to the normalized given vector
* Example Playground https://playground.babylonjs.com/#QYBWV4#46
* @param vector defines the vector to normalize
* @returns a new Vector2
*/
static Normalize(vector) {
return Vector2.NormalizeToRef(vector, new Vector2());
}
/**
* Normalize a given vector into a second one
* Example Playground https://playground.babylonjs.com/#QYBWV4#50
* @param vector defines the vector to normalize
* @param result defines the vector where to store the result
* @returns result input
*/
static NormalizeToRef(vector, result) {
vector.normalizeToRef(result);
return result;
}
/**
* Gets a new Vector2 set with the minimal coordinate values from the "left" and "right" vectors
* Example Playground https://playground.babylonjs.com/#QYBWV4#86
* @param left defines 1st vector
* @param right defines 2nd vector
* @returns a new Vector2
*/
static Minimize(left, right) {
const x = left.x < right.x ? left.x : right.x;
const y = left.y < right.y ? left.y : right.y;
return new Vector2(x, y);
}
/**
* Gets a new Vector2 set with the maximal coordinate values from the "left" and "right" vectors
* Example Playground https://playground.babylonjs.com/#QYBWV4#86
* @param left defines 1st vector
* @param right defines 2nd vector
* @returns a new Vector2
*/
static Maximize(left, right) {
const x = left.x > right.x ? left.x : right.x;
const y = left.y > right.y ? left.y : right.y;
return new Vector2(x, y);
}
/**
* Gets a new Vector2 set with the transformed coordinates of the given vector by the given transformation matrix
* Example Playground https://playground.babylonjs.com/#QYBWV4#17
* @param vector defines the vector to transform
* @param transformation defines the matrix to apply
* @returns a new Vector2
*/
static Transform(vector, transformation) {
return Vector2.TransformToRef(vector, transformation, new Vector2());
}
/**
* Transforms the given vector coordinates by the given transformation matrix and stores the result in the vector "result" coordinates
* Example Playground https://playground.babylonjs.com/#QYBWV4#19
* @param vector defines the vector to transform
* @param transformation defines the matrix to apply
* @param result defines the target vector
* @returns result input
*/
static TransformToRef(vector, transformation, result) {
const m = transformation.m;
const x = vector.x * m[0] + vector.y * m[4] + m[12];
const y = vector.x * m[1] + vector.y * m[5] + m[13];
result.x = x;
result.y = y;
return result;
}
/**
* Determines if a given vector is included in a triangle
* Example Playground https://playground.babylonjs.com/#QYBWV4#87
* @param p defines the vector to test
* @param p0 defines 1st triangle point
* @param p1 defines 2nd triangle point
* @param p2 defines 3rd triangle point
* @returns true if the point "p" is in the triangle defined by the vectors "p0", "p1", "p2"
*/
static PointInTriangle(p, p0, p1, p2) {
const a = (1 / 2) * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
const sign = a < 0 ? -1 : 1;
const s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
const t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
return s > 0 && t > 0 && s + t < 2 * a * sign;
}
/**
* Gets the distance between the vectors "value1" and "value2"
* Example Playground https://playground.babylonjs.com/#QYBWV4#71
* @param value1 defines first vector
* @param value2 defines second vector
* @returns the distance between vectors
*/
static Distance(value1, value2) {
return Math.sqrt(Vector2.DistanceSquared(value1, value2));
}
/**
* Returns the squared distance between the vectors "value1" and "value2"
* Example Playground https://playground.babylonjs.com/#QYBWV4#72
* @param value1 defines first vector
* @param value2 defines second vector
* @returns the squared distance between vectors
*/
static DistanceSquared(value1, value2) {
const x = value1.x - value2.x;
const y = value1.y - value2.y;
return x * x + y * y;
}
/**
* Gets a new Vector2 located at the center of the vectors "value1" and "value2"
* Example Playground https://playground.babylonjs.com/#QYBWV4#86
* Example Playground https://playground.babylonjs.com/#QYBWV4#66
* @param value1 defines first vector
* @param value2 defines second vector
* @returns a new Vector2
*/
static Center(value1, value2) {
return Vector2.CenterToRef(value1, value2, new Vector2());
}
/**
* Gets the center of the vectors "value1" and "value2" and stores the result in the vector "ref"
* Example Playground https://playground.babylonjs.com/#QYBWV4#66
* @param value1 defines first vector
* @param value2 defines second vector
* @param ref defines third vector
* @returns ref
*/
static CenterToRef(value1, value2, ref) {
return ref.copyFromFloats((value1.x + value2.x) / 2, (value1.y + value2.y) / 2);
}
/**
* Gets the shortest distance (float) between the point "p" and the segment defined by the two points "segA" and "segB".
* Example Playground https://playground.babylonjs.com/#QYBWV4#77
* @param p defines the middle point
* @param segA defines one point of the segment
* @param segB defines the other point of the segment
* @returns the shortest distance
*/
static DistanceOfPointFromSegment(p, segA, segB) {
const l2 = Vector2.DistanceSquared(segA, segB);
if (l2 === 0.0) {
return Vector2.Distance(p, segA);
}
const v = segB.subtract(segA);
const t = Math.max(0, Math.min(1, Vector2.Dot(p.subtract(segA), v) / l2));
const proj = segA.add(v.multiplyByFloats(t, t));
return Vector2.Distance(p, proj);
}
}
/**
* If the first vector is flagged with integers (as everything is 0,0), V8 stores all of the properties as integers internally because it doesn't know any better yet.
* If subsequent vectors are created with non-integer values, V8 determines that it would be best to represent these properties as doubles instead of integers,
* and henceforth it will use floating-point representation for all Vector2 instances that it creates.
* But the original Vector2 instances are unchanged and has a "deprecated map".
* If we keep using the Vector2 instances from step 1, it will now be a poison pill which will mess up optimizations in any code it touches.
*/
Vector2._V8PerformanceHack = new Vector2(0.5, 0.5);
Vector2._ZeroReadOnly = Vector2.Zero();
Vector2;
Object.defineProperties(Vector2.prototype, {
dimension: { value: [2] },
rank: { value: 1 },
});
/**
* Class used to store (x,y,z) vector representation
* A Vector3 is the main object used in 3D geometry
* It can represent either the coordinates of a point the space, either a direction
* Reminder: js uses a left handed forward facing system
* Example Playground - Overview - https://playground.babylonjs.com/#R1F8YU
*/
export class Vector3 {
/** Gets or sets the x coordinate */
get x() {
return this._x;
}
set x(value) {
this._x = value;
this._isDirty = true;
}
/** Gets or sets the y coordinate */
get y() {
return this._y;
}
set y(value) {
this._y = value;
this._isDirty = true;
}
/** Gets or sets the z coordinate */
get z() {
return this._z;
}
set z(value) {
this._z = value;
this._isDirty = true;
}
/**
* Creates a new Vector3 object from the given x, y, z (floats) coordinates.
* @param x defines the first coordinates (on X axis)
* @param y defines the second coordinates (on Y axis)
* @param z defines the third coordinates (on Z axis)
*/
constructor(x = 0, y = 0, z = 0) {
/** @internal */
this._isDirty = true;
this._x = x;
this._y = y;
this._z = z;
}
/**
* Creates a string representation of the Vector3
* Example Playground https://playground.babylonjs.com/#R1F8YU#67
* @returns a string with the Vector3 coordinates.
*/
toString() {
return `{X: ${this._x} Y: ${this._y} Z: ${this._z}}`;
}
/**
* Gets the class name
* @returns the string "Vector3"
*/
getClassName() {
return "Vector3";
}
/**
* Creates the Vector3 hash code
* @returns a number which tends to be unique between Vector3 instances
*/
getHashCode() {
const x = ExtractAsInt(this._x);
const y = ExtractAsInt(this._y);
const z = ExtractAsInt(this._z);
let hash = x;
hash = (hash * 397) ^ y;
hash = (hash * 397) ^ z;
return hash;
}
// Operators
/**
* Creates an array containing three elements : the coordinates of the Vector3
* Example Playground https://playground.babylonjs.com/#R1F8YU#10
* @returns a new array of numbers
*/
asArray() {
return [this._x, this._y, this._z];
}
/**
* Populates the given array or Float32Array from the given index with the successive coordinates of the Vector3
* Example Playground https://playground.babylonjs.com/#R1F8YU#65
* @param array defines the destination array
* @param index defines the offset in the destination array
* @returns the current Vector3
*/
toArray(array, index = 0) {
array[index] = this._x;
array[index + 1] = this._y;
array[index + 2] = this._z;
return this;
}
/**
* Update the current vector from an array
* Example Playground https://playground.babylonjs.com/#R1F8YU#24
* @param array defines the destination array
* @param offset defines the offset in the destination array
* @returns the current Vector3
*/
fromArray(array, offset = 0) {
Vector3.FromArrayToRef(array, offset, this);
return this;
}
/**
* Converts the current Vector3 into a quaternion (considering that the Vector3 contains Euler angles representation of a rotation)
* Example Playground https://playground.babylonjs.com/#R1F8YU#66
* @returns a new Quaternion object, computed from the Vector3 coordinates
*/
toQuaternion() {
return Quaternion.RotationYawPitchRoll(this._y, this._x, this._z);
}
/**
* Adds the given vector to the current Vector3
* Example Playground https://playground.babylonjs.com/#R1F8YU#4
* @param otherVector defines the second operand
* @returns the current updated Vector3
*/
addInPlace(otherVector) {
this._x += otherVector._x;
this._y += otherVector._y;
this._z += otherVector._z;
this._isDirty = true;
return this;
}
/**
* Adds the given coordinates to the current Vector3
* Example Playground https://playground.babylonjs.com/#R1F8YU#5
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the current updated Vector3
*/
addInPlaceFromFloats(x, y, z) {
this._x += x;
this._y += y;
this._z += z;
this._isDirty = true;
return this;
}
/**
* Gets a new Vector3, result of the addition the current Vector3 and the given vector
* Example Playground https://playground.babylonjs.com/#R1F8YU#3
* @param otherVector defines the second operand
* @returns the resulting Vector3
*/
add(otherVector) {
return new Vector3(this._x + otherVector._x, this._y + otherVector._y, this._z + otherVector._z);
}
/**
* Adds the current Vector3 to the given one and stores the result in the vector "result"
* Example Playground https://playground.babylonjs.com/#R1F8YU#6
* @param otherVector defines the second operand
* @param result defines the Vector3 object where to store the result
* @returns the result
*/
addToRef(otherVector, result) {
result._x = this._x + otherVector._x;
result._y = this._y + otherVector._y;
result._z = this._z + otherVector._z;
result._isDirty = true;
return result;
}
/**
* Subtract the given vector from the current Vector3
* Example Playground https://playground.babylonjs.com/#R1F8YU#61
* @param otherVector defines the second operand
* @returns the current updated Vector3
*/
subtractInPlace(otherVector) {
this._x -= otherVector._x;
this._y -= otherVector._y;
this._z -= otherVector._z;
this._isDirty = true;
return this;
}
/**
* Returns a new Vector3, result of the subtraction of the given vector from the current Vector3
* Example Playground https://playground.babylonjs.com/#R1F8YU#60
* @param otherVector defines the second operand
* @returns the resulting Vector3
*/
subtract(otherVector) {
return new Vector3(this._x - otherVector._x, this._y - otherVector._y, this._z - otherVector._z);
}
/**
* Subtracts the given vector from the current Vector3 and stores the result in the vector "result".
* Example Playground https://playground.babylonjs.com/#R1F8YU#63
* @param otherVector defines the second operand
* @param result defines the Vector3 object where to store the result
* @returns the result
*/
subtractToRef(otherVector, result) {
return this.subtractFromFloatsToRef(otherVector._x, otherVector._y, otherVector._z, result);
}
/**
* Returns a new Vector3 set with the subtraction of the given floats from the current Vector3 coordinates
* Example Playground https://playground.babylonjs.com/#R1F8YU#62
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @returns the resulting Vector3
*/
subtractFromFloats(x, y, z) {
return new Vector3(this._x - x, this._y - y, this._z - z);
}
/**
* Subtracts the given floats from the current Vector3 coordinates and set the given vector "result" with this result
* Example Playground https://playground.babylonjs.com/#R1F8YU#64
* @param x defines the x coordinate of the operand
* @param y defines the y coordinate of the operand
* @param z defines the z coordinate of the operand
* @param result defines the Vector3 object where to store the result
* @returns the result
*/
subtractFromFloatsToRef(x, y, z, result) {
result._x = this._x - x;
result._y = this._y - y;
result._z = this._z - z;
result._isDirty = true;
return result;
}
/**
* Gets a new Vector3 set with the current Vector3 negated coordinates
* Example Playground https://playground.babylonjs.com/#R1F8YU#35
* @returns a new Vector3
*/
negate() {
return new Vector3(-this._x, -this._y, -this._z);
}
/**
* Negate this vector in place
* Example Playground https://playground.babylonjs.com/#R1F8YU#36
* @returns this
*/
negateInPlace() {
this._x *= -1;
this._y *= -1;
this._z *= -1;
this._isDirty = true;
return this;
}
/**
* Negate the current Vector3 and stores the result in the given vector "result" coordinates
* Example Playground https://playground.babylonjs.com/#R1F8YU#37
* @param result defines the Vector3 object where to store the result
* @returns the result
*/
negateToRef(result) {
result._x = this._x * -1;
result._y = this._y * -1;
result._z = this._z * -1;
result._isDirty = true;
return result;
}
/**
* Multiplies the Vector3 coordinates by the float "scale"
* Example Playground https://playground.babylonjs.com/#R1F8YU#56
* @param scale defines the multiplier factor
* @returns the current updated Vector3
*/
scaleInPlace(scale) {
this._x *= scale;
this._y *= scale;
this._z *= scale;
this._isDirty = true;
return this;
}
/**
* Returns a new Vector3 set with the current Vector3 coordinates multiplied by the float "scale"
* Example Playground https://playground.babylonjs.com/#R1F8YU#53
* @param scale defines the multiplier factor
* @returns a new Vector3
*/
scale(scale) {
return new Vector3(this._x * scale, this._y * scale, this._z * scale);
}
/**
* Multiplies the current Vector3 coordinates by the float "scale" and stores the result in the given vector "result" coordinates
* Example Playground https://playground.babylonjs.com/#R1F8YU#57
* @param scale defines the multiplier factor
* @param result defines the Vector3 object where to store the result
* @returns the result
*/
scaleToRef(scale, result) {
result._x = this._x * scale;
result._y = this._y * scale;
result._z = this._z * scale;
result._isDirty = true;
return result;
}
/**
* Creates a vector normal (perpendicular) to the current Vector3 and stores the result in the given vector
* Out of the infinite possibilities the normal chosen is the one formed by rotating the current vector
* 90 degrees about an axis which lies perpendicular to the current vector
* and its projection on the xz plane. In the case of a current vector in the xz plane
* the normal is calculated to be along the y axis.
* Example Playground https://playground.babylonjs.com/#R1F8YU#230
* Example Playground https://playground.babylonjs.com/#R1F8YU#231
* @param result defines the Vector3 object where to store the resultant normal
* @returns the result
*/
getNormalToRef(result) {
/**
* Calculates the spherical coordinates of the current vector
* so saves on memory rather than importing whole Spherical Class
*/
const radius = this.length();
let theta = Math.acos(this._y / radius);
const phi = Math.atan2(this._z, this._x);
//makes angle 90 degs to current vector
if (theta > Math.PI / 2) {
theta -= Math.PI / 2;
}
else {
theta += Math.PI / 2;
}
//Calculates resutant normal vector from spherical coordinate of perpendicular vector
const x = radius * Math.sin(theta) * Math.cos(phi);
const y = radius * Math.cos(theta);
const z = radius * Math.sin(theta) * Math.sin(phi);
result.set(x, y, z);
return result;
}
/**
* Rotates the vector using the given unit quaternion and stores the new vector in result
* Example Playground https://playground.babylonjs.com/#R1F8YU#9
* @param q the unit quaternion representing the rotation
* @param result the output vector
* @returns the result
*/
applyRotationQuaternionToRef(q, result) {
// Derived from https://raw.org/proof/vector-rotation-using-quaternions/
const vx = this._x, vy = this._y, vz = this._z;
const qx = q._x, qy = q._y, qz = q._z, qw = q._w;
// t = 2q x v