UNPKG

unreal.js

Version:

A pak reader for games like VALORANT & Fortnite written in Node.JS

471 lines (470 loc) 15.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FVector = void 0; const FArchive_1 = require("../../../reader/FArchive"); const FVector2D_1 = require("./FVector2D"); const FVector4_1 = require("./FVector4"); const FColor_1 = require("./FColor"); const FIntVector_1 = require("./FIntVector"); const FIntPoint_1 = require("./FIntPoint"); const Const_1 = require("../../../../util/Const"); const UnrealMathUtility_1 = require("./UnrealMathUtility"); /** Allowed error for a normalized vector (against squared magnitude) */ const THRESH_VECTOR_NORMALIZED = 0.01; /** * Represents an UE4 FVector * @implements {IStructType} */ class FVector { /** DO NOT USE THIS CONSTRUCTOR, THIS IS FOR THE LIBRARY */ constructor(arg1, arg2, arg3) { if (typeof arg1 === "number" && !arg2) { this.x = arg1; this.y = arg1; this.z = arg1; } else if (arg1 instanceof FArchive_1.FArchive) { this.x = arg1.readFloat32(); this.y = arg1.readFloat32(); this.z = arg1.readFloat32(); } else if (arg1 instanceof FVector4_1.FVector4) { this.x = arg1.x; this.y = arg1.y; this.z = arg1.z; } else if (arg1 instanceof FColor_1.FLinearColor) { this.x = arg1.r; this.y = arg1.g; this.z = arg1.b; } else if (arg1 instanceof FIntVector_1.FIntVector) { this.x = arg1.x; this.y = arg1.y; this.z = arg1.z; } else if (arg1 instanceof FIntPoint_1.FIntPoint) { this.x = arg1.x; this.y = arg1.y; this.z = 0; } else if (arg1 instanceof FVector2D_1.FVector2D && typeof arg2 === "number") { this.x = arg1.x; this.y = arg1.y; this.z = arg2; } else if (arg1 == null) { this.x = 0; this.y = 0; this.z = 0; } else { this.x = arg1; this.y = arg2; this.z = arg3; } } /** * Serializes this * @param {FArchiveWriter} Ar Writer to use * @returns {void} * @public */ serialize(Ar) { Ar.writeFloat32(this.x); Ar.writeFloat32(this.y); Ar.writeFloat32(this.z); } /** * Turns this into json * @returns {any} Json * @public */ toJson() { return { x: this.x, y: this.y, z: this.z }; } /** * Copy another FVector into this one * @param {FVector} other The other vector * @returns {FVector} Reference to vector after copy * @public */ set(other) { this.x = other.x; this.y = other.y; this.x = other.x; return this; } /** * Calculate cross product between this and another vector * @param {FVector} v The other vector * @returns {FVector} The cross product * @public */ xor(v) { return new FVector(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x); } /** * Calculate the dot product between this and another vector * @param {FVector} v The other vector * @returns {number} The dot product * @public */ or(v) { return this.x * v.x + this.y * v.y + this.z * v.z; } /** DO NOT USE THIS METHOD, THIS IS FOR THE LIBRARY */ "+"(arg) { if (arg instanceof FVector) return new FVector(this.x + arg.x, this.y + arg.y, this.z + arg.z); return new FVector(this.x + arg, this.y + arg, this.z + arg); } /** DO NOT USE THIS METHOD, THIS IS FOR THE LIBRARY */ "-"(arg) { if (arg instanceof FVector) return new FVector(this.x - arg.x, this.y - arg.y, this.z - arg.z); return new FVector(this.x - arg, this.y - arg, this.z - arg); } /** DO NOT USE THIS METHOD, THIS IS FOR THE LIBRARY */ "*"(arg) { if (arg instanceof FVector) return new FVector(this.x * arg.x, this.y * arg.y, this.z * arg.z); return new FVector(this.x * arg, this.y * arg, this.z * arg); } /** DO NOT USE THIS METHOD, THIS IS FOR THE LIBRARY */ "/"(arg) { if (arg instanceof FVector) return new FVector(this.x / arg.x, this.y / arg.y, this.z / arg.z); const rScale = 1 / arg; return new FVector(this.x * rScale, this.y * rScale, this.z * rScale); } /** DO NOT USE THIS METHOD, THIS IS FOR THE LIBRARY */ equals(x, y) { if (x instanceof FVector && y != null) { return Math.abs(this.x - x.x) <= y && Math.abs(this.y - x.y) <= y && Math.abs(this.z - x.z) <= y; } else { if (this === x) return true; if (!(x instanceof FVector)) return false; return this.x === x.x && this.y === x.y && this.z === x.y; } } /** * Checks Whether all components are equal * @param {number} tolerance Tolerance to use * @returns {boolean} * @public */ allComponentsEqual(tolerance = Const_1.KINDA_SMALL_NUMBER) { return Math.abs(this.x - this.y) <= tolerance && Math.abs(this.x - this.z) <= tolerance && Math.abs(this.y - this.z) <= tolerance; } /** * Get a negated copy of the vector * @returns {FVector} A negated copy of the vector * @public */ unaryMinus() { return new FVector(-this.x, -this.y, -this.z); } /** * Adds another vector to this * Uses component-wise addition * @param {FVector} v Vector to add to this * @returns {void} * @public */ "+="(v) { this.x += v.x; this.y += v.y; this.z += v.z; } /** * Subtracts another vector from this * Uses component-wise subtraction * @param {FVector} v Vector to subtract from this * @returns {void} * @public */ "-="(v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; } /** DO NOT USE THIS METHOD, THIS IS FOR THE LIBRARY */ "*="(arg) { if (arg instanceof FVector) { this.x *= arg.x; this.y *= arg.y; this.z *= arg.z; } this.x *= arg; this.y *= arg; this.z *= arg; } /** * Divides the vector by a number * @param {FVector} v What to divide this vector by * @returns {void} * @public */ "/="(v) { this.x /= v.x; this.y /= v.y; this.z /= v.z; } /** * Gets specific component of the vector * @param {number} index the index of vector component * @returns {number} Copy of the component * @throws {RangeError} If index is < 0 or > 2 * @public */ get(index) { if (index === 0) return this.x; if (index === 1) return this.y; if (index === 2) return this.z; throw new RangeError(`Received index: ${index}, but max./min. index: 2/0`); } /** * Sets specific component of the vector * @param {number} index the index of vector component * @param {number} value the new value of vector component * @returns {void} * @throws {RangeError} If index is < 0 or > 2 * @public */ set0(index, value) { if (index === 0) this.x = value; if (index === 1) this.y = value; if (index === 2) this.z = value; throw new RangeError(`Received index: ${index}, but max./min. index: 2/0`); } /** * Set the values of the vector directly * @param {number} x New X coordinate * @param {number} y New Y coordinate * @param {number} z New Z coordinate * @returns {void} * @public */ set1(x, y, z) { this.x = x; this.y = y; this.z = z; } /** * Get the maximum value of the vector's components * @returns {number} The maximum value of the vector's components * @public */ getMax() { return Math.max(Math.max(this.x, this.y), this.z); } /** * Get the maximum absolute value of the vector's components * @returns {number} The maximum absolute value of the vector's components * @public */ getAbsMax() { return Math.max(Math.max(Math.abs(this.x), Math.abs(this.y)), Math.abs(this.z)); } /** * Get the minimum value of the vector's components * @returns {number} The minimum value of the vector's components * @public */ getMin() { return Math.min(Math.min(this.x, this.y), this.z); } /** * Get the minimum absolute value of the vector's components * @returns {number} The minimum absolute value of the vector's components * @public */ getAbsMin() { return Math.min(Math.min(Math.abs(this.x), Math.abs(this.y)), Math.abs(this.z)); } /** * Gets the component-wise min of two vectors * @param {FVector} other Other FVector * @returns {FVector} New instance * @public */ componentMin(other) { return new FVector(Math.min(this.x, other.x), Math.min(this.y, other.y), Math.min(this.z, other.z)); } /** * Gets the component-wise max of two vectors * @param {FVector} other Other FVector * @returns {FVector} New instance * @public */ componentMax(other) { return new FVector(Math.max(this.x, other.x), Math.max(this.y, other.y), Math.max(this.z, other.z)); } /** * Get a copy of this vector with absolute value of each component * @returns {FVector} A copy of this vector with absolute value of each component * @public */ getAbs() { return new FVector(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); } /** * The length (magnitude) of this vector * @type {number} * @public */ get size() { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); } /** * The squared length of this vector * @type {number} * @public */ get sizeSquared() { return this.x * this.x + this.y * this.y + this.z * this.z; } /** * The length of the 2D components of this vector * @type {number} * @public */ get size2D() { return Math.sqrt(this.x * this.x + this.y * this.y); } /** * The squared length of the 2D components of this vector * @type {number} * @public */ get sizeSquared2D() { return this.x * this.x + this.y * this.y; } /** * Checks whether vector is near to zero within a specified tolerance * @param {number} tolerance Error tolerance * @returns {boolean} Whether the vector is near to zero, false otherwise * @public */ isNearlyZero(tolerance = Const_1.KINDA_SMALL_NUMBER) { return Math.abs(this.x) <= tolerance && Math.abs(this.y) <= tolerance && Math.abs(this.z) <= tolerance; } /** * Whether all components of the vector are exactly zero * @type {boolean} * @public */ get isZero() { return this.x === 0 && this.y === 0 && this.z === 0; } /** * Check if the vector is of unit length, with specified tolerance * @param {number} lengthSquaredTolerance Tolerance against squared length * @returns {boolean} Whether the vector is a unit vector within the specified tolerance * @public */ isUnit(lengthSquaredTolerance = Const_1.KINDA_SMALL_NUMBER) { return Math.abs(1 - this.sizeSquared) < lengthSquaredTolerance; } /** * Whether vector is normalized * @type {boolean} * @public */ get isNormalized() { return Math.abs(1 - this.sizeSquared) < THRESH_VECTOR_NORMALIZED; } // TODO port more methods /** * Get a textual representation of this vector * @returns {string} A string describing the vector * @public */ toString() { return `X=${this.x.toLocaleString()} Y=${this.y.toLocaleString()} Z=${this.z.toLocaleString()}`; } /** * Squared distance between two points * @param {FVector} other The other point * @returns {number} The squared distance between two points * @public */ distSquared(other) { return UnrealMathUtility_1.square(other.x - this.x) + UnrealMathUtility_1.square(other.y - this.y); } /** * Calculate the cross product of two vectors * @param {FVector} a The first vector * @param {FVector} b The second vector * @returns {number} The cross product * @public */ static crossProduct(a, b) { return a.xor(b); } /** * Calculate the dot product of two vectors * @param {FVector} a The first vector * @param {FVector} b The second vector * @returns {number} The dot product * @public */ static dotProduct(a, b) { return a.or(b); } /** * Util to calculate distance from a point to a bounding box * @param {FVector} mins 3D Point defining the lower values of the axis of the bound box * @param {FVector} maxs 3D Point defining the lower values of the axis of the bound box * @param {FVector} point 3D position of interest * @returns {number} the distance from the Point to the bounding box * @public * @static */ static computeSquaredDistanceFromBoxToPoint(mins, maxs, point) { // Accumulates the distance as we iterate axis let distSquared = 0; // Check each axis for min/max and add the distance accordingly // NOTE: Loop manually unrolled for > 2x speed up if (point.x < mins.x) { distSquared += (point.x - mins.x) * (point.x - mins.x); } else if (point.x > maxs.x) { distSquared += (point.x - maxs.x) * (point.x - maxs.x); } if (point.y < mins.y) { distSquared += (point.y - mins.y) * (point.y - mins.y); } else if (point.y > maxs.y) { distSquared += (point.y - maxs.y) * (point.y - maxs.y); } if (point.z < mins.z) { distSquared += (point.z - mins.z) * (point.z - mins.z); } else if (point.z > maxs.z) { distSquared += (point.z - maxs.z) * (point.z - maxs.z); } return distSquared; } } exports.FVector = FVector;