import {Quaternion} from '../index.js';
/**
* Creates three-dimensional vectors.
*
* @example
*
* // without chaining
* const vector = new Vector3(3, 2, 1);
* vector.add(new Vector3(1, 0, -1));
*
* @example
*
* // with chaining
* const vector = new Vector3(3, 2, 1).add(new Vector3(1, 0, -1));
*/
class Vector3 {
/**
* Stores the x component.
* @type {number}
* @private
*/
$x;
/**
* Stores the y component.
* @type {number}
* @private
*/
$y;
/**
* Stores the z component.
* @type {number}
* @private
*/
$z;
/**
* Gets the x component.
* @type {number}
* @public
*/
get x() {
return this.$x;
}
/**
* Gets the y component.
* @type {number}
* @public
*/
get y() {
return this.$y;
}
/**
* Gets the z component.
* @type {number}
* @public
*/
get z() {
return this.$z;
}
/**
* Creates a new three-dimensional vector.
* @param {number} $x The x component of the vector to create.
* @param {number} $y The y component of the vector to create.
* @param {number} $z The z component of the vector to create.
*/
constructor($x, $y, $z) {
this.$x = $x;
this.$y = $y;
this.$z = $z;
}
/**
* Creates a new vector from the given vector.
* @param {Vector3} $vector The given vector.
* @returns {Vector3}
* @public
* @static
*/
static from($vector) {
return $vector.clone();
}
/**
* Adds the given vector.
* @param {Vector3} $vector The vector to add.
* @returns {this}
* @public
*/
add($vector) {
const x = this.$x;
const y = this.$y;
const z = this.$z;
this.$x = x + $vector.x;
this.$y = y + $vector.y;
this.$z = z + $vector.z;
return this;
}
/**
* Clones the vector.
* @returns {Vector3}
* @public
*/
clone() {
const x = this.$x;
const y = this.$y;
const z = this.$z;
return new Vector3(x, y, z);
}
/**
* Checks the equality with the given vector.
* @param {Vector3} $vector The vector to check with.
* @returns {boolean}
* @public
*/
equal($vector) {
return this.$x === $vector.x
&& this.$y === $vector.y
&& this.$z === $vector.z;
}
/**
* Gets the length of the vector.
* @returns {number}
* @public
*/
length() {
const x = this.$x;
const y = this.$y;
const z = this.$z;
return Math.sqrt(x * x + y * y + z * z);
}
/**
* Multiplies with the given vector.
* @param {Vector3} $vector The vector to multiply with.
* @returns {this}
* @public
*/
multiply($vector) {
const x = this.$x;
const y = this.$y;
const z = this.$z;
this.$x = x * $vector.x;
this.$y = y * $vector.y;
this.$z = z * $vector.z;
return this;
}
/**
* Negates the vector.
* @returns {this}
* @public
*/
negate() {
const x = this.$x;
const y = this.$y;
const z = this.$z;
this.$x = - x;
this.$y = - y;
this.$z = - z;
return this;
}
/**
* Normalizes the vector.
* @returns {this}
* @public
*/
normalize() {
const x = this.$x;
const y = this.$y;
const z = this.$z;
let length = x * x + y * y + z * z;
if (length > 0) {
length = 1 / Math.sqrt(length);
}
this.$x = x * length;
this.$y = y * length;
this.$z = z * length;
return this;
}
/**
* Rotates the vector.
* @param {Quaternion} $quaternion The rotation to apply.
* @returns {this}
* @public
*/
rotate($quaternion) {
const x = this.$x;
const y = this.$y;
const z = this.$z;
const xq = $quaternion.x;
const yq = $quaternion.y;
const zq = $quaternion.z;
const wq = $quaternion.w;
let xu = yq * z - zq * y;
let yu = zq * x - xq * z;
let zu = xq * y - yq * x;
let xv = yq * zu - zq * yu;
let yv = zq * xu - xq * zu;
let zv = xq * yu - yq * xu;
const w = wq * 2;
xu *= w;
yu *= w;
zu *= w;
xv *= 2;
yv *= 2;
zv *= 2;
this.$x = x + xu + xv;
this.$y = y + yu + yv;
this.$z = z + zu + zv;
return this;
}
/**
* Scales the vector by the given scalar factor.
* @param {number} $factor The scalar factor to multiply with.
* @returns {this}
* @public
*/
scale($factor) {
const x = this.$x;
const y = this.$y;
const z = this.$z;
this.$x = x * $factor;
this.$y = y * $factor;
this.$z = z * $factor;
return this;
}
/**
* Subtracts the given vector.
* @param {Vector3} $vector The vector to subtract.
* @returns {this}
* @public
*/
subtract($vector) {
const x = this.$x;
const y = this.$y;
const z = this.$z;
this.$x = x - $vector.x;
this.$y = y - $vector.y;
this.$z = z - $vector.z;
return this;
}
}
export {
Vector3
};
export default Vector3;