UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

591 lines 19.4 kB
/** * Implementation of a quaternion. * Represents rotation in 3d space * * Iterating through a Quaternion instance will yield its components `(x, y, z, w)` in the corresponding order. * Note that a quaternion must be {@link normalize}d to properly represent rotation. Check documentation of individual operations when in doubt. * @see https://en.wikipedia.org/wiki/Quaternion * @implements Iterable<number> * * @author Alex Goldring * @copyright Company Named Limited (c) 2025 */ export class Quaternion implements Iterable<number> { /** * * @param {Vector3} axis * @param {number} angle * @returns {Quaternion} */ static fromAxisAngle(axis: Vector3, angle: number): Quaternion; /** * Create a randomly oriented quaternion * @param {function} [random] random number generator function * @returns {Quaternion} */ static random(random?: Function): Quaternion; /** * Convenience constructor * Used XYZ angle order (see {@link fromEulerAnglesXYZ}) * @param {number} x in radians * @param {number} y in radians * @param {number} z in radians * @returns {Quaternion} */ static fromEulerAngles(x: number, y: number, z: number): Quaternion; /** * Behaves similarly to Unity's Quaternion `RotateToward` method * @param {Quaternion} result * @param {Quaternion} from * @param {Quaternion} to * @param {number} max_delta in radians */ static rotateTowards(result: Quaternion, from: Quaternion, to: Quaternion, max_delta: number): void; /** * * @param {number} [x=0] * @param {number} [y=0] * @param {number} [z=0] * @param {number} [w=1] * @constructor */ constructor(x?: number, y?: number, z?: number, w?: number); /** * * @type {number} */ x: number; /** * * @type {number} */ y: number; /** * * @type {number} */ z: number; /** * * @type {number} */ w: number; /** * Fires when the value of the quaternion changes * Signature of the signal data is as follows: * (new_x, new_y, new_z, new_w, old_x, old_y, old_z, old_w) * @readonly * @type {Signal<number, number, number, number, number, number, number, number>} */ readonly onChanged: Signal<number, number, number, number, number, number, number, number>; /** * * @param {number} v */ set 0(arg: number); /** * * @return {number} */ get 0(): number; /** * * @param {number} v */ set 1(arg: number); /** * * @return {number} */ get 1(): number; /** * * @param {number} v */ set 2(arg: number); /** * * @return {number} */ get 2(): number; /** * * @param {number} v */ set 3(arg: number); /** * * @return {number} */ get 3(): number; /** * Orient quaternion on a `forward` vector, with the spin matching `up` vector * Useful for `lookAt` operations, such as for camera or inverse kinematics. * Normalizes input, meaning input does not have to be normalized. * * NOTE: `forward` and `up` vectors being the same is allowed, but you will likely get unexpected rotation along the look axis, so prefer not to do it. * * @param {number} fx forward vector * @param {number} fy forward vector * @param {number} fz forward vector * @param {number} ux up vector * @param {number} uy up vector * @param {number} uz up vector * @returns {this} */ _lookRotation(fx: number, fy: number, fz: number, ux: number, uy: number, uz: number): this; /** * Orient quaternion to align with the `forward` direction. * @param {Vector3} forward Does not need to be normalized. * @param {Vector3} [up=Vector3.up] Does not need to be normalized. * @returns {this} */ lookRotation(forward: Vector3, up?: Vector3): this; /** * Vector dot product in 4 dimensions * @param {Quaternion} other * @return {number} */ dot(other: Quaternion): number; /** * Makes this quaternion into an inverse of the other * @param {Quaternion} other * @returns {this} */ copyInverse(other: Quaternion): this; /** * Calculates the inverse. * Correctly handles unnormalized quaternions. * * If your quaternion is normalized, you can use {@link conjugate} instead for speed. * @returns {this} * @see conjugate */ invert(): this; /** * NOTE: this is the same as {@link invert} if the quaternion is normalized. * @returns {this} * @see invert */ conjugate(): this; /** * Returns angle between this orientation and another * @param {Quaternion} other * @return {number} angle in radians */ angleTo(other: Quaternion): number; /** * Set quaternion from axis + angle definition * @param {Vector3} axis * @param {number} angle * @returns {this} */ fromAxisAngle(axis: Vector3, angle: number): this; /** * * @param {number} axis_x * @param {number} axis_y * @param {number} axis_z * @param {number} angle * @returns {this} */ _fromAxisAngle(axis_x: number, axis_y: number, axis_z: number, angle: number): this; /** * Given a direction axis, compute rotation quaternions from current rotation to that axis as swing and twist. Swing moves to a given orientation while without "twisting", * `twist` just the twist around the given axis, no change in orientation. * @param {Vector3} axis * @param {Quaternion} swing Swing quaternion will be written here * @param {Quaternion} twist Twist quaternion will be written here * @returns {void} * @see slerp */ computeSwingAndTwist(axis: Vector3, swing: Quaternion, twist: Quaternion): void; /** * Compute rotation (twist) around input axis * @param {Vector3} axis * @returns {number} in radians */ computeTwistAngle(axis: Vector3): number; /** * Decompose quaternion to the axis of rotation and angle around this axis. * @param {Vector3} out_axis axis will be written here * @returns {number} angle in radians */ toAxisAngle(out_axis: Vector3): number; /** * * @returns {this} */ normalize(): this; /** * * @param {number} val * @return {this} */ multiplyScalar(val: number): this; /** * @param {Quaternion} other * @returns {this} */ multiply(other: Quaternion): this; /** * * @param {Quaternion} first * @param {Quaternion} second * @returns {this} */ multiplyQuaternions(first: Quaternion, second: Quaternion): this; /** * * @param {number} ax * @param {number} ay * @param {number} az * @param {number} aw * @param {number} bx * @param {number} by * @param {number} bz * @param {number} bw * @returns {this} */ _multiplyQuaternions(ax: number, ay: number, az: number, aw: number, bx: number, by: number, bz: number, bw: number): this; /** * * @return {number} */ length(): number; /** * * @param {Quaternion} other * @param {number} max_delta in radians * @returns {this} */ rotateTowards(other: Quaternion, max_delta: number): this; /** * * @param {Vector3} source * @param {Vector3} target * @param {Vector3} [up] * @see lookRotation */ lookAt(source: Vector3, target: Vector3, up?: Vector3): void; /** * @deprecated use {@link fromEulerAnglesXYZ} or others specifically. * * @param {number} x * @param {number} y * @param {number} z * @param {String} [order='XYZ'] a combination of capital letters X,Y,Z. Examples: XYZ, YXZ * @returns {this} * * @see fromEulerAnglesXYZ * @see fromEulerAnglesYXZ * @see fromEulerAnglesZXY * @see fromEulerAnglesZYX * @see fromEulerAnglesYZX * @see fromEulerAnglesXZY */ __setFromEuler(x: number, y: number, z: number, order?: string): this; /** * @see https://localcoder.org/euler-angle-to-quaternion-then-quaternion-to-euler-angle * @see https://discourse.mcneel.com/t/what-is-the-right-method-to-convert-quaternion-to-plane-using-rhinocommon/92411/21?page=2 * @param {Vector3} result */ toEulerAnglesXYZ(result: Vector3): void; /** * Adapted from http://bediyap.com/programming/convert-quaternion-to-euler-rotations/ * @param {Vector3} result */ toEulerAnglesYXZ(result: Vector3): void; /** * Adapted from http://bediyap.com/programming/convert-quaternion-to-euler-rotations/ * @param {Vector3} result */ toEulerAnglesZYX(result: Vector3): void; /** * Set rotation from Euler angles in degrees. * * Order is explicitly XYZ. * * Utility shortcut, same as `fromEulerAnglesXYZ(x * π / 180, y * π / 180, z * π / 180)` * * @param {number} [x] angle in degrees * @param {number} [y] angle in degrees * @param {number} [z] angle in degrees * @returns {this} * * @see fromEulerAnglesXYZ */ fromDegrees(x?: number, y?: number, z?: number): this; /** * XYZ order * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206 * @param {number} x angle in X axis in radians * @param {number} y angle in Y axis in radians * @param {number} z angle in Z axis in radians * @returns {this} */ fromEulerAnglesXYZ(x: number, y: number, z: number): this; /** * YXZ order * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206 * @param {number} x angle in X axis in radians * @param {number} y angle in Y axis in radians * @param {number} z angle in Z axis in radians * @returns {this} */ fromEulerAnglesYXZ(x: number, y: number, z: number): this; /** * ZXY order * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206 * @param {number} x angle in X axis in radians * @param {number} y angle in Y axis in radians * @param {number} z angle in Z axis in radians * @returns {this} */ fromEulerAnglesZXY(x: number, y: number, z: number): this; /** * ZYX order * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206 * @param {number} x angle in X axis in radians * @param {number} y angle in Y axis in radians * @param {number} z angle in Z axis in radians * @returns {this} */ fromEulerAnglesZYX(x: number, y: number, z: number): this; /** * YZX order * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206 * @param {number} x angle in X axis in radians * @param {number} y angle in Y axis in radians * @param {number} z angle in Z axis in radians * @returns {this} */ fromEulerAnglesYZX(x: number, y: number, z: number): this; /** * XZY order * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206 * @param {number} x angle in X axis in radians * @param {number} y angle in Y axis in radians * @param {number} z angle in Z axis in radians * @returns {this} */ fromEulerAnglesXZY(x: number, y: number, z: number): this; /** * NOTE: Vectors need to be normalized * * @param {Vector3} from Must be normalized * @param {Vector3} to Must be normalized * @returns {this} */ fromUnitVectors(from: Vector3, to: Vector3): this; /** * @param {number[]|Float32Array} m4x4 * @returns {this} */ setFromRotationMatrix(m4x4: number[] | Float32Array): this; /** * This algorithm comes from "Quaternion Calculus and Fast Animation", * Ken Shoemake, 1987 SIGGRAPH course notes * @see https://gitlab.com/libeigen/eigen/-/blob/master/Eigen/src/Geometry/Quaternion.h#L813 * @param {number} m11 * @param {number} m12 * @param {number} m13 * @param {number} m21 * @param {number} m22 * @param {number} m23 * @param {number} m31 * @param {number} m32 * @param {number} m33 * @returns {this} */ __setFromRotationMatrix(m11: number, m12: number, m13: number, m21: number, m22: number, m23: number, m31: number, m32: number, m33: number): this; /** * Linear interpolation * @param {Quaternion} other * @param {number} t fractional value between 0 and 1 * @returns {this} */ lerp(other: Quaternion, t: number): this; /** * Linear interpolation of two quaternions * Pretty good, not as good as slerp, but close enough for most application * @param {Quaternion} first * @param {Quaternion} second * @param {number} t * @returns {this} */ lerpQuaternions(first: Quaternion, second: Quaternion, t: number): this; /** * Spherical linear interpolation * @param {Quaternion} from * @param {Quaternion} to * @param {number} t coefficient, how much between the input quaternions? Must be a value between 0 and 1 * @returns {this} */ slerpQuaternions(from: Quaternion, to: Quaternion, t: number): this; /** * @see https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/quat.js * @param {Quaternion} other * @param {number} t * @returns {this} */ slerp(other: Quaternion, t: number): this; /** * * @param {function(x:number,y:number,z:number,w:number)} handler * @param {*} [thisArg] * @returns {this} */ process(handler: any, thisArg?: any): this; /** * * @param {Quaternion} other * @returns {this} */ copy(other: Quaternion): this; /** * * @returns {Quaternion} */ clone(): Quaternion; /** * Set current value of the quaternion * You *MUST* use this method in order for {@link Quaternion#onChanged} signal to be fired * @param {number} x * @param {number} y * @param {number} z * @param {number} w * @returns {this} */ set(x: number, y: number, z: number, w: number): this; toJSON(): { x: number; y: number; z: number; w: number; }; /** * * @param obj * @return {this} */ fromJSON(obj: any): this; /** * * @param {BinaryBuffer} buffer */ toBinaryBuffer(buffer: BinaryBuffer): void; /** * * @param {BinaryBuffer} buffer */ fromBinaryBuffer(buffer: BinaryBuffer): void; /** * * @param {BinaryBuffer} buffer */ toBinaryBufferFloat32(buffer: BinaryBuffer): void; /** * * @param {BinaryBuffer} buffer */ fromBinaryBufferFloat32(buffer: BinaryBuffer): void; /** * * @param {number[]} array * @param {number} [offset] * @returns {this} */ fromArray(array: number[], offset?: number): this; /** * * @param {number[]} [array] * @param {number} [offset] * @returns {number[]} */ toArray(array?: number[], offset?: number): number[]; /** * Strict equality check * @param {Quaternion} other * @returns {boolean} * @see roughlyEquals */ equals(other: Quaternion): boolean; /** * * @returns {number} integer hash */ hash(): number; /** * Check for approximate equality between two quaternions * @param {Quaternion} other * @param {number} [tolerance] * @return {boolean} */ roughlyEquals(other: Quaternion, tolerance?: number): boolean; /** * * @param {number} x * @param {number} y * @param {number} z * @param {number} w * @param {number} [tolerance] acceptable difference value per coordinate * @return {boolean} */ _roughlyEquals(x: number, y: number, z: number, w: number, tolerance?: number): boolean; /** * @deprecated use {@link random} instead * @param {function():number} random */ setRandom(random: () => number): void; /** * Randomly orient current quaternion * @param {function():number} [random=Math.random] Random number generator function. */ random(random?: () => number): this; toString(): string; /** * @deprecated use `fromArray` */ readFromArray: (array: number[], offset?: number) => this; /** * @deprecated use `toArray` */ writeToArray: (array?: number[], offset?: number) => number[]; /** * @deprecated use `toArray` */ asArray: (array?: number[], offset?: number) => number[]; fromEulerAngles: (x: number, y: number, z: number) => this; /** * Shortcut for type checking * @readonly * @type {boolean} */ readonly isQuaternion: boolean; /** * Making quaternion iterable * @returns {Generator<number>} */ [Symbol.iterator](): Generator<number>; } export namespace Quaternion { let identity: Quaternion; let typeName: string; } export default Quaternion; import Signal from "../events/signal/Signal.js"; import Vector3 from "./Vector3.js"; //# sourceMappingURL=Quaternion.d.ts.map