// Quaternion export interface Quaternion { x: number; y: number; z: number; w: number; } /** @class * @subcategory Math * */ export class Quaternion { x: number; y: number; z: number; w: number; constructor(x?: number, y?: number, z?: number, w?: number) { this.x = x || 0; this.y = y || 0; this.z = z || 0; this.w = w !== undefined ? w : 1; } set(x: number, y: number, z: number, w: number) { this.x = x; this.y = y; this.z = z; this.w = w; return this; } copy(q: Quaternion) { this.x = q.x; this.y = q.y; this.z = q.z; this.w = q.w; return this; } conjugate() { this.x *= -1; this.y *= -1; this.z *= -1; return this; } inverse() { return this.conjugate().normalize(); } length() { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); } lengthxyz() { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); } normalize() { let l = this.length(); if (l === 0) { this.x = 0; this.y = 0; this.z = 0; this.w = 1; } else { l = 1 / l; this.x *= l; this.y *= l; this.z *= l; this.w *= l; } return this; } multiply(q: any) { return this.multiplyQuaternions(this, q); } multiplyScalar(s: number) { this.x *= s; this.y *= s; this.z *= s; this.w *= s; return this; } multiplyQuaternions(a: Quaternion, b: Quaternion) { const qax = a.x; const qay = a.y; const qaz = a.z; const qaw = a.w; const qbx = b.x; const qby = b.y; const qbz = b.z; const qbw = b.w; this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; return this; } sub(q: Quaternion) { this.x -= q.x; this.y -= q.y; this.z -= q.z; this.w -= q.w; return this; } clone() { return new Quaternion(this.x, this.y, this.z, this.w); } setFromEuler(e: Quaternion) { const c1 = Math.cos(e.x / 2); const c2 = Math.cos(e.y / 2); const c3 = Math.cos(e.z / 2); const s1 = Math.sin(e.x / 2); const s2 = Math.sin(e.y / 2); const s3 = Math.sin(e.z / 2); this.x = s1 * c2 * c3 + c1 * s2 * s3; this.y = c1 * s2 * c3 - s1 * c2 * s3; this.z = c1 * c2 * s3 + s1 * s2 * c3; this.w = c1 * c2 * c3 - s1 * s2 * s3; return this; } }