the-world-engine
Version:
three.js based, unity like game engine for browser
481 lines (473 loc) • 13.4 kB
JavaScript
import { clamp } from "three/src/math/MathUtils";
import { Quaternion } from "three/src/Three";
export class ObservableQuaternion {
isQuaternion=true;
ti;
ii;
si;
ks;
_onChangeCallback;
ei;
ri;
constructor(t = 0, s = 0, i = 0, h = 1) {
this.ti = t;
this.ii = s;
this.si = i;
this.ks = h;
this._onChangeCallback = () => {};
this.ei = () => {};
this.ri = () => {};
}
onBeforeGetComponent(t) {
this.ri = t;
}
onBeforeChange(t) {
this.ei = t;
}
static slerp(t, s, i, h) {
console.warn("THREE.Quaternion: Static .slerp() has been deprecated. Use qm.slerpQuaternions( qa, qb, t ) instead.");
return i.slerpQuaternions(t, s, h);
}
static slerpFlat(t, s, i, h, e, r, n) {
let a = i[h + 0], o = i[h + 1], u = i[h + 2], c = i[h + 3];
const l = e[r + 0], M = e[r + 1], f = e[r + 2], m = e[r + 3];
if (n === 0) {
t[s + 0] = a;
t[s + 1] = o;
t[s + 2] = u;
t[s + 3] = c;
return;
}
if (n === 1) {
t[s + 0] = l;
t[s + 1] = M;
t[s + 2] = f;
t[s + 3] = m;
return;
}
if (c !== m || a !== l || o !== M || u !== f) {
let t = 1 - n;
const s = a * l + o * M + u * f + c * m, i = s >= 0 ? 1 : -1, h = 1 - s * s;
if (h > Number.EPSILON) {
const e = Math.sqrt(h), r = Math.atan2(e, s * i);
t = Math.sin(t * r) / e;
n = Math.sin(n * r) / e;
}
const e = n * i;
a = a * t + l * e;
o = o * t + M * e;
u = u * t + f * e;
c = c * t + m * e;
if (t === 1 - n) {
const t = 1 / Math.sqrt(a * a + o * o + u * u + c * c);
a *= t;
o *= t;
u *= t;
c *= t;
}
}
t[s] = a;
t[s + 1] = o;
t[s + 2] = u;
t[s + 3] = c;
}
static multiplyQuaternionsFlat(t, s, i, h, e, r) {
const n = i[h];
const a = i[h + 1];
const o = i[h + 2];
const u = i[h + 3];
const c = e[r];
const l = e[r + 1];
const M = e[r + 2];
const f = e[r + 3];
t[s] = n * f + u * c + a * M - o * l;
t[s + 1] = a * f + u * l + o * c - n * M;
t[s + 2] = o * f + u * M + n * l - a * c;
t[s + 3] = u * f - n * c - a * l - o * M;
return t;
}
get _x() {
this.ri();
return this.ti;
}
set _x(t) {
this.ti = t;
}
get _y() {
this.ri();
return this.ii;
}
set _y(t) {
this.ii = t;
}
get _z() {
this.ri();
return this.si;
}
set _z(t) {
this.si = t;
}
get _w() {
this.ri();
return this.ks;
}
set _w(t) {
this.ks = t;
}
get x() {
this.ri();
return this.ti;
}
set x(t) {
this.ei();
this.ti = t;
this._onChangeCallback();
}
get y() {
this.ri();
return this.ii;
}
set y(t) {
this.ei();
this.ii = t;
this._onChangeCallback();
}
get z() {
this.ri();
return this.si;
}
set z(t) {
this.ei();
this.si = t;
this._onChangeCallback();
}
get w() {
this.ri();
return this.ks;
}
set w(t) {
this.ei();
this.ks = t;
this._onChangeCallback();
}
set(t, s, i, h) {
this.ei();
this.ti = t;
this.ii = s;
this.si = i;
this.ks = h;
this._onChangeCallback();
return this;
}
clone() {
this.ri();
return new Quaternion(this.ti, this.ii, this.si, this.ks);
}
copy(t) {
this.ei();
this.ti = t.x;
this.ii = t.y;
this.si = t.z;
this.ks = t.w;
this._onChangeCallback();
return this;
}
setFromEuler(t, s) {
if (!(t && t.isEuler)) {
throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");
}
const i = t._x, h = t._y, e = t._z, r = t._order;
const n = Math.cos;
const a = Math.sin;
const o = n(i / 2);
const u = n(h / 2);
const c = n(e / 2);
const l = a(i / 2);
const M = a(h / 2);
const f = a(e / 2);
this.ei();
switch (r) {
case "XYZ":
this.ti = l * u * c + o * M * f;
this.ii = o * M * c - l * u * f;
this.si = o * u * f + l * M * c;
this.ks = o * u * c - l * M * f;
break;
case "YXZ":
this.ti = l * u * c + o * M * f;
this.ii = o * M * c - l * u * f;
this.si = o * u * f - l * M * c;
this.ks = o * u * c + l * M * f;
break;
case "ZXY":
this.ti = l * u * c - o * M * f;
this.ii = o * M * c + l * u * f;
this.si = o * u * f + l * M * c;
this.ks = o * u * c - l * M * f;
break;
case "ZYX":
this.ti = l * u * c - o * M * f;
this.ii = o * M * c + l * u * f;
this.si = o * u * f - l * M * c;
this.ks = o * u * c + l * M * f;
break;
case "YZX":
this.ti = l * u * c + o * M * f;
this.ii = o * M * c + l * u * f;
this.si = o * u * f - l * M * c;
this.ks = o * u * c - l * M * f;
break;
case "XZY":
this.ti = l * u * c - o * M * f;
this.ii = o * M * c - l * u * f;
this.si = o * u * f + l * M * c;
this.ks = o * u * c + l * M * f;
break;
default:
console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: " + r);
}
if (s !== false) this._onChangeCallback();
return this;
}
setFromAxisAngle(t, s) {
const i = s / 2, h = Math.sin(i);
this.ei();
this.ti = t.x * h;
this.ii = t.y * h;
this.si = t.z * h;
this.ks = Math.cos(i);
this._onChangeCallback();
return this;
}
setFromRotationMatrix(t) {
const s = t.elements, i = s[0], h = s[4], e = s[8], r = s[1], n = s[5], a = s[9], o = s[2], u = s[6], c = s[10], l = i + n + c;
this.ei();
if (l > 0) {
const t = .5 / Math.sqrt(l + 1);
this.ks = .25 / t;
this.ti = (u - a) * t;
this.ii = (e - o) * t;
this.si = (r - h) * t;
} else if (i > n && i > c) {
const t = 2 * Math.sqrt(1 + i - n - c);
this.ks = (u - a) / t;
this.ti = .25 * t;
this.ii = (h + r) / t;
this.si = (e + o) / t;
} else if (n > c) {
const t = 2 * Math.sqrt(1 + n - i - c);
this.ks = (e - o) / t;
this.ti = (h + r) / t;
this.ii = .25 * t;
this.si = (a + u) / t;
} else {
const t = 2 * Math.sqrt(1 + c - i - n);
this.ks = (r - h) / t;
this.ti = (e + o) / t;
this.ii = (a + u) / t;
this.si = .25 * t;
}
this._onChangeCallback();
return this;
}
setFromUnitVectors(t, s) {
let i = t.dot(s) + 1;
this.ei();
if (i < Number.EPSILON) {
i = 0;
if (Math.abs(t.x) > Math.abs(t.z)) {
this.ti = -t.y;
this.ii = t.x;
this.si = 0;
this.ks = i;
} else {
this.ti = 0;
this.ii = -t.z;
this.si = t.y;
this.ks = i;
}
} else {
this.ti = t.y * s.z - t.z * s.y;
this.ii = t.z * s.x - t.x * s.z;
this.si = t.x * s.y - t.y * s.x;
this.ks = i;
}
return this.normalize();
}
angleTo(t) {
return 2 * Math.acos(Math.abs(clamp(this.dot(t), -1, 1)));
}
rotateTowards(t, s) {
const i = this.angleTo(t);
if (i === 0) return this;
const h = Math.min(1, s / i);
this.slerp(t, h);
return this;
}
identity() {
return this.set(0, 0, 0, 1);
}
invert() {
return this.conjugate();
}
conjugate() {
this.ri();
this.ei();
this.ti *= -1;
this.ii *= -1;
this.si *= -1;
this._onChangeCallback();
return this;
}
dot(t) {
this.ri();
return this.ti * t._x + this.ii * t._y + this.si * t._z + this.ks * t._w;
}
lengthSq() {
this.ri();
return this.ti * this.ti + this.ii * this.ii + this.si * this.si + this.ks * this.ks;
}
length() {
this.ri();
return Math.sqrt(this.ti * this.ti + this.ii * this.ii + this.si * this.si + this.ks * this.ks);
}
normalize() {
let t = this.length();
if (t === 0) {
this.ei();
this.ti = 0;
this.ii = 0;
this.si = 0;
this.ks = 1;
} else {
t = 1 / t;
this.ri();
this.ei();
this.ti = this.ti * t;
this.ii = this.ii * t;
this.si = this.si * t;
this.ks = this.ks * t;
}
this._onChangeCallback();
return this;
}
multiply(t, s) {
if (s !== undefined) {
console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.");
return this.multiplyQuaternions(t, s);
}
if (t._x === 0 && t._y === 0 && t._z === 0 && t._w === 1) return this;
return this.multiplyQuaternions(this, t);
}
premultiply(t) {
return this.multiplyQuaternions(t, this);
}
multiplyQuaternions(t, s) {
const i = t._x, h = t._y, e = t._z, r = t._w;
const n = s._x, a = s._y, o = s._z, u = s._w;
this.ei();
this.ti = i * u + r * n + h * o - e * a;
this.ii = h * u + r * a + e * n - i * o;
this.si = e * u + r * o + i * a - h * n;
this.ks = r * u - i * n - h * a - e * o;
this._onChangeCallback();
return this;
}
slerp(t, s) {
if (s === 0) return this;
if (s === 1) return this.copy(t);
this.ri();
const i = this.ti, h = this.ii, e = this.si, r = this.ks;
let n = r * t._w + i * t._x + h * t._y + e * t._z;
this.ei();
if (n < 0) {
this.ks = -t._w;
this.ti = -t._x;
this.ii = -t._y;
this.si = -t._z;
n = -n;
} else {
this.copy(t);
}
if (n >= 1) {
this.ks = r;
this.ti = i;
this.ii = h;
this.si = e;
return this;
}
const a = 1 - n * n;
if (a <= Number.EPSILON) {
const t = 1 - s;
this.ks = t * r + s * this.ks;
this.ti = t * i + s * this.ti;
this.ii = t * h + s * this.ii;
this.si = t * e + s * this.si;
this.normalize();
return this;
}
const o = Math.sqrt(a);
const u = Math.atan2(o, n);
const c = Math.sin((1 - s) * u) / o, l = Math.sin(s * u) / o;
this.ks = r * c + this.ks * l;
this.ti = i * c + this.ti * l;
this.ii = h * c + this.ii * l;
this.si = e * c + this.si * l;
this._onChangeCallback();
return this;
}
slerpQuaternions(t, s, i) {
return this.copy(t).slerp(s, i);
}
random() {
const t = Math.random();
const s = Math.sqrt(1 - t);
const i = Math.sqrt(t);
const h = 2 * Math.PI * Math.random();
const e = 2 * Math.PI * Math.random();
return this.set(s * Math.cos(h), i * Math.sin(e), i * Math.cos(e), s * Math.sin(h));
}
equals(t) {
this.ri();
return t._x === this.ti && t._y === this.ii && t._z === this.si && t._w === this.ks;
}
fromArray(t, s = 0) {
if (this.ti === t[s] && this.ii === t[s + 1] && this.si === t[s + 2] && this.ks === t[s + 3]) return this;
this.ei();
this.ti = t[s];
this.ii = t[s + 1];
this.si = t[s + 2];
this.ks = t[s + 3];
this._onChangeCallback();
return this;
}
toArray(t = [], s = 0) {
this.ri();
t[s] = this.ti;
t[s + 1] = this.ii;
t[s + 2] = this.si;
t[s + 3] = this.ks;
return t;
}
fromBufferAttribute(t, s) {
this.ti = t.getX(s);
this.ii = t.getY(s);
this.si = t.getZ(s);
this.ks = t.getW(s);
return this;
}
_onChange(t) {
this._onChangeCallback = t;
return this;
}
* [Symbol.iterator]() {
this.ri();
yield this.ti;
this.ri();
yield this.ii;
this.ri();
yield this.si;
this.ri();
yield this.ks;
}
}