export class Quaternion { | |
constructor(x = 0, y = 0, z = 0, w = 1) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.w = w; | |
} | |
static fromEuler(x, y, z) { | |
const cx = Math.cos(x * 0.5); | |
const cy = Math.cos(y * 0.5); | |
const cz = Math.cos(z * 0.5); | |
const sx = Math.sin(x * 0.5); | |
const sy = Math.sin(y * 0.5); | |
const sz = Math.sin(z * 0.5); | |
return new Quaternion( | |
sx * cy * cz + cx * sy * sz, | |
cx * sy * cz - sx * cy * sz, | |
cx * cy * sz + sx * sy * cz, | |
cx * cy * cz - sx * sy * sz | |
); | |
} | |
static multiply(a, b) { | |
return new Quaternion( | |
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y, | |
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x, | |
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w, | |
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z | |
); | |
} | |
normalize() { | |
const len = Math.sqrt( | |
this.x * this.x + | |
this.y * this.y + | |
this.z * this.z + | |
this.w * this.w | |
); | |
if (len === 0) return this; | |
const invLen = 1 / len; | |
return new Quaternion( | |
this.x * invLen, | |
this.y * invLen, | |
this.z * invLen, | |
this.w * invLen | |
); | |
} | |
clone() { | |
return new Quaternion(this.x, this.y, this.z, this.w); | |
} | |
} | |