UNPKG

@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
/* 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