UNPKG

the-world-engine

Version:

three.js based, unity like game engine for browser

1,126 lines (1,080 loc) 25.4 kB
import { b2_pi, b2_epsilon, b2MakeArray } from "./b2_settings.js"; export const b2_pi_over_180 = b2_pi / 180; export const b2_180_over_pi = 180 / b2_pi; export const b2_two_pi = 2 * b2_pi; export const b2Abs = Math.abs; export function b2Min(t, s) { return t < s ? t : s; } export function b2Max(t, s) { return t > s ? t : s; } export function b2Clamp(t, s, i) { return t < s ? s : t > i ? i : t; } export function b2Swap(t, s) { const i = t[0]; t[0] = s[0]; s[0] = i; } export const b2IsValid = isFinite; export function b2Sq(t) { return t * t; } export function b2InvSqrt(t) { return 1 / Math.sqrt(t); } export const b2Sqrt = Math.sqrt; export const b2Pow = Math.pow; export function b2DegToRad(t) { return t * b2_pi_over_180; } export function b2RadToDeg(t) { return t * b2_180_over_pi; } export const b2Cos = Math.cos; export const b2Sin = Math.sin; export const b2Acos = Math.acos; export const b2Asin = Math.asin; export const b2Atan2 = Math.atan2; export function b2NextPowerOfTwo(t) { t |= t >> 1 & 2147483647; t |= t >> 2 & 1073741823; t |= t >> 4 & 268435455; t |= t >> 8 & 16777215; t |= t >> 16 & 65535; return t + 1; } export function b2IsPowerOfTwo(t) { return t > 0 && (t & t - 1) === 0; } export function b2Random() { return Math.random() * 2 - 1; } export function b2RandomRange(t, s) { return (s - t) * Math.random() + t; } export class b2Vec2 { constructor(t = 0, s = 0) { this.x = t; this.y = s; } Clone() { return new b2Vec2(this.x, this.y); } SetZero() { this.x = 0; this.y = 0; return this; } Set(t, s) { this.x = t; this.y = s; return this; } Copy(t) { this.x = t.x; this.y = t.y; return this; } SelfAdd(t) { this.x += t.x; this.y += t.y; return this; } SelfAddXY(t, s) { this.x += t; this.y += s; return this; } SelfSub(t) { this.x -= t.x; this.y -= t.y; return this; } SelfSubXY(t, s) { this.x -= t; this.y -= s; return this; } SelfMul(t) { this.x *= t; this.y *= t; return this; } SelfMulAdd(t, s) { this.x += t * s.x; this.y += t * s.y; return this; } SelfMulSub(t, s) { this.x -= t * s.x; this.y -= t * s.y; return this; } Dot(t) { return this.x * t.x + this.y * t.y; } Cross(t) { return this.x * t.y - this.y * t.x; } Length() { const t = this.x, s = this.y; return Math.sqrt(t * t + s * s); } LengthSquared() { const t = this.x, s = this.y; return t * t + s * s; } Normalize() { const t = this.Length(); if (t >= b2_epsilon) { const s = 1 / t; this.x *= s; this.y *= s; } return t; } SelfNormalize() { const t = this.Length(); if (t >= b2_epsilon) { const s = 1 / t; this.x *= s; this.y *= s; } return this; } SelfRotate(t) { const s = Math.cos(t); const i = Math.sin(t); const e = this.x; this.x = s * e - i * this.y; this.y = i * e + s * this.y; return this; } SelfRotateCosSin(t, s) { const i = this.x; this.x = t * i - s * this.y; this.y = s * i + t * this.y; return this; } IsValid() { return isFinite(this.x) && isFinite(this.y); } SelfCrossVS(t) { const s = this.x; this.x = t * this.y; this.y = -t * s; return this; } SelfCrossSV(t) { const s = this.x; this.x = -t * this.y; this.y = t * s; return this; } SelfMinV(t) { this.x = b2Min(this.x, t.x); this.y = b2Min(this.y, t.y); return this; } SelfMaxV(t) { this.x = b2Max(this.x, t.x); this.y = b2Max(this.y, t.y); return this; } SelfAbs() { this.x = b2Abs(this.x); this.y = b2Abs(this.y); return this; } SelfNeg() { this.x = -this.x; this.y = -this.y; return this; } SelfSkew() { const t = this.x; this.x = -this.y; this.y = t; return this; } static MakeArray(t) { return b2MakeArray(t, (t => new b2Vec2)); } static AbsV(t, s) { s.x = b2Abs(t.x); s.y = b2Abs(t.y); return s; } static MinV(t, s, i) { i.x = b2Min(t.x, s.x); i.y = b2Min(t.y, s.y); return i; } static MaxV(t, s, i) { i.x = b2Max(t.x, s.x); i.y = b2Max(t.y, s.y); return i; } static ClampV(t, s, i, e) { e.x = b2Clamp(t.x, s.x, i.x); e.y = b2Clamp(t.y, s.y, i.y); return e; } static RotateV(t, s, i) { const e = t.x, r = t.y; const h = Math.cos(s); const n = Math.sin(s); i.x = h * e - n * r; i.y = n * e + h * r; return i; } static DotVV(t, s) { return t.x * s.x + t.y * s.y; } static CrossVV(t, s) { return t.x * s.y - t.y * s.x; } static CrossVS(t, s, i) { const e = t.x; i.x = s * t.y; i.y = -s * e; return i; } static CrossVOne(t, s) { const i = t.x; s.x = t.y; s.y = -i; return s; } static CrossSV(t, s, i) { const e = s.x; i.x = -t * s.y; i.y = t * e; return i; } static CrossOneV(t, s) { const i = t.x; s.x = -t.y; s.y = i; return s; } static AddVV(t, s, i) { i.x = t.x + s.x; i.y = t.y + s.y; return i; } static SubVV(t, s, i) { i.x = t.x - s.x; i.y = t.y - s.y; return i; } static MulSV(t, s, i) { i.x = s.x * t; i.y = s.y * t; return i; } static MulVS(t, s, i) { i.x = t.x * s; i.y = t.y * s; return i; } static AddVMulSV(t, s, i, e) { e.x = t.x + s * i.x; e.y = t.y + s * i.y; return e; } static SubVMulSV(t, s, i, e) { e.x = t.x - s * i.x; e.y = t.y - s * i.y; return e; } static AddVCrossSV(t, s, i, e) { const r = i.x; e.x = t.x - s * i.y; e.y = t.y + s * r; return e; } static MidVV(t, s, i) { i.x = (t.x + s.x) * .5; i.y = (t.y + s.y) * .5; return i; } static ExtVV(t, s, i) { i.x = (s.x - t.x) * .5; i.y = (s.y - t.y) * .5; return i; } static IsEqualToV(t, s) { return t.x === s.x && t.y === s.y; } static DistanceVV(t, s) { const i = t.x - s.x; const e = t.y - s.y; return Math.sqrt(i * i + e * e); } static DistanceSquaredVV(t, s) { const i = t.x - s.x; const e = t.y - s.y; return i * i + e * e; } static NegV(t, s) { s.x = -t.x; s.y = -t.y; return s; } } b2Vec2.ZERO = new b2Vec2(0, 0); b2Vec2.UNITX = new b2Vec2(1, 0); b2Vec2.UNITY = new b2Vec2(0, 1); b2Vec2.s_t0 = new b2Vec2; b2Vec2.s_t1 = new b2Vec2; b2Vec2.s_t2 = new b2Vec2; b2Vec2.s_t3 = new b2Vec2; export const b2Vec2_zero = new b2Vec2(0, 0); export class b2TypedVec2 { constructor(...t) { if (t[0] instanceof Float32Array) { if (t[0].length !== 2) { throw new Error; } this.data = t[0]; } else { const s = typeof t[0] === "number" ? t[0] : 0; const i = typeof t[1] === "number" ? t[1] : 0; this.data = new Float32Array([ s, i ]); } } get x() { return this.data[0]; } set x(t) { this.data[0] = t; } get y() { return this.data[1]; } set y(t) { this.data[1] = t; } Clone() { return new b2TypedVec2(new Float32Array(this.data)); } SetZero() { this.x = 0; this.y = 0; return this; } Set(t, s) { this.x = t; this.y = s; return this; } Copy(t) { if (t instanceof b2TypedVec2) { this.data.set(t.data); } else { this.x = t.x; this.y = t.y; } return this; } SelfAdd(t) { this.x += t.x; this.y += t.y; return this; } SelfAddXY(t, s) { this.x += t; this.y += s; return this; } SelfSub(t) { this.x -= t.x; this.y -= t.y; return this; } SelfSubXY(t, s) { this.x -= t; this.y -= s; return this; } SelfMul(t) { this.x *= t; this.y *= t; return this; } SelfMulAdd(t, s) { this.x += t * s.x; this.y += t * s.y; return this; } SelfMulSub(t, s) { this.x -= t * s.x; this.y -= t * s.y; return this; } Dot(t) { return this.x * t.x + this.y * t.y; } Cross(t) { return this.x * t.y - this.y * t.x; } Length() { const t = this.x, s = this.y; return Math.sqrt(t * t + s * s); } LengthSquared() { const t = this.x, s = this.y; return t * t + s * s; } Normalize() { const t = this.Length(); if (t >= b2_epsilon) { const s = 1 / t; this.x *= s; this.y *= s; } return t; } SelfNormalize() { const t = this.Length(); if (t >= b2_epsilon) { const s = 1 / t; this.x *= s; this.y *= s; } return this; } SelfRotate(t) { const s = Math.cos(t); const i = Math.sin(t); const e = this.x; this.x = s * e - i * this.y; this.y = i * e + s * this.y; return this; } SelfRotateCosSin(t, s) { const i = this.x; this.x = t * i - s * this.y; this.y = s * i + t * this.y; return this; } IsValid() { return isFinite(this.x) && isFinite(this.y); } SelfCrossVS(t) { const s = this.x; this.x = t * this.y; this.y = -t * s; return this; } SelfCrossSV(t) { const s = this.x; this.x = -t * this.y; this.y = t * s; return this; } SelfMinV(t) { this.x = b2Min(this.x, t.x); this.y = b2Min(this.y, t.y); return this; } SelfMaxV(t) { this.x = b2Max(this.x, t.x); this.y = b2Max(this.y, t.y); return this; } SelfAbs() { this.x = b2Abs(this.x); this.y = b2Abs(this.y); return this; } SelfNeg() { this.x = -this.x; this.y = -this.y; return this; } SelfSkew() { const t = this.x; this.x = -this.y; this.y = t; return this; } } export class b2Vec3 { constructor(...t) { if (t[0] instanceof Float32Array) { if (t[0].length !== 3) { throw new Error; } this.data = t[0]; } else { const s = typeof t[0] === "number" ? t[0] : 0; const i = typeof t[1] === "number" ? t[1] : 0; const e = typeof t[2] === "number" ? t[2] : 0; this.data = new Float32Array([ s, i, e ]); } } get x() { return this.data[0]; } set x(t) { this.data[0] = t; } get y() { return this.data[1]; } set y(t) { this.data[1] = t; } get z() { return this.data[2]; } set z(t) { this.data[2] = t; } Clone() { return new b2Vec3(this.x, this.y, this.z); } SetZero() { this.x = 0; this.y = 0; this.z = 0; return this; } SetXYZ(t, s, i) { this.x = t; this.y = s; this.z = i; return this; } Copy(t) { this.x = t.x; this.y = t.y; this.z = t.z; return this; } SelfNeg() { this.x = -this.x; this.y = -this.y; this.z = -this.z; return this; } SelfAdd(t) { this.x += t.x; this.y += t.y; this.z += t.z; return this; } SelfAddXYZ(t, s, i) { this.x += t; this.y += s; this.z += i; return this; } SelfSub(t) { this.x -= t.x; this.y -= t.y; this.z -= t.z; return this; } SelfSubXYZ(t, s, i) { this.x -= t; this.y -= s; this.z -= i; return this; } SelfMul(t) { this.x *= t; this.y *= t; this.z *= t; return this; } static DotV3V3(t, s) { return t.x * s.x + t.y * s.y + t.z * s.z; } static CrossV3V3(t, s, i) { const e = t.x, r = t.y, h = t.z; const n = s.x, o = s.y, c = s.z; i.x = r * c - h * o; i.y = h * n - e * c; i.z = e * o - r * n; return i; } } b2Vec3.ZERO = new b2Vec3(0, 0, 0); b2Vec3.s_t0 = new b2Vec3; export class b2Mat22 { constructor() { this.ex = new b2Vec2(1, 0); this.ey = new b2Vec2(0, 1); } Clone() { return (new b2Mat22).Copy(this); } static FromVV(t, s) { return (new b2Mat22).SetVV(t, s); } static FromSSSS(t, s, i, e) { return (new b2Mat22).SetSSSS(t, s, i, e); } static FromAngle(t) { return (new b2Mat22).SetAngle(t); } SetSSSS(t, s, i, e) { this.ex.Set(t, i); this.ey.Set(s, e); return this; } SetVV(t, s) { this.ex.Copy(t); this.ey.Copy(s); return this; } SetAngle(t) { const s = Math.cos(t); const i = Math.sin(t); this.ex.Set(s, i); this.ey.Set(-i, s); return this; } Copy(t) { this.ex.Copy(t.ex); this.ey.Copy(t.ey); return this; } SetIdentity() { this.ex.Set(1, 0); this.ey.Set(0, 1); return this; } SetZero() { this.ex.SetZero(); this.ey.SetZero(); return this; } GetAngle() { return Math.atan2(this.ex.y, this.ex.x); } GetInverse(t) { const s = this.ex.x; const i = this.ey.x; const e = this.ex.y; const r = this.ey.y; let h = s * r - i * e; if (h !== 0) { h = 1 / h; } t.ex.x = h * r; t.ey.x = -h * i; t.ex.y = -h * e; t.ey.y = h * s; return t; } Solve(t, s, i) { const e = this.ex.x, r = this.ey.x; const h = this.ex.y, n = this.ey.y; let o = e * n - r * h; if (o !== 0) { o = 1 / o; } i.x = o * (n * t - r * s); i.y = o * (e * s - h * t); return i; } SelfAbs() { this.ex.SelfAbs(); this.ey.SelfAbs(); return this; } SelfInv() { this.GetInverse(this); return this; } SelfAddM(t) { this.ex.SelfAdd(t.ex); this.ey.SelfAdd(t.ey); return this; } SelfSubM(t) { this.ex.SelfSub(t.ex); this.ey.SelfSub(t.ey); return this; } static AbsM(t, s) { const i = t.ex, e = t.ey; s.ex.x = b2Abs(i.x); s.ex.y = b2Abs(i.y); s.ey.x = b2Abs(e.x); s.ey.y = b2Abs(e.y); return s; } static MulMV(t, s, i) { const e = t.ex, r = t.ey; const h = s.x, n = s.y; i.x = e.x * h + r.x * n; i.y = e.y * h + r.y * n; return i; } static MulTMV(t, s, i) { const e = t.ex, r = t.ey; const h = s.x, n = s.y; i.x = e.x * h + e.y * n; i.y = r.x * h + r.y * n; return i; } static AddMM(t, s, i) { const e = t.ex, r = t.ey; const h = s.ex, n = s.ey; i.ex.x = e.x + h.x; i.ex.y = e.y + h.y; i.ey.x = r.x + n.x; i.ey.y = r.y + n.y; return i; } static MulMM(t, s, i) { const e = t.ex.x, r = t.ex.y; const h = t.ey.x, n = t.ey.y; const o = s.ex.x, c = s.ex.y; const u = s.ey.x, a = s.ey.y; i.ex.x = e * o + h * c; i.ex.y = r * o + n * c; i.ey.x = e * u + h * a; i.ey.y = r * u + n * a; return i; } static MulTMM(t, s, i) { const e = t.ex.x, r = t.ex.y; const h = t.ey.x, n = t.ey.y; const o = s.ex.x, c = s.ex.y; const u = s.ey.x, a = s.ey.y; i.ex.x = e * o + r * c; i.ex.y = h * o + n * c; i.ey.x = e * u + r * a; i.ey.y = h * u + n * a; return i; } } b2Mat22.IDENTITY = new b2Mat22; export class b2Mat33 { constructor() { this.data = new Float32Array([ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]); this.ex = new b2Vec3(this.data.subarray(0, 3)); this.ey = new b2Vec3(this.data.subarray(3, 6)); this.ez = new b2Vec3(this.data.subarray(6, 9)); } Clone() { return (new b2Mat33).Copy(this); } SetVVV(t, s, i) { this.ex.Copy(t); this.ey.Copy(s); this.ez.Copy(i); return this; } Copy(t) { this.ex.Copy(t.ex); this.ey.Copy(t.ey); this.ez.Copy(t.ez); return this; } SetIdentity() { this.ex.SetXYZ(1, 0, 0); this.ey.SetXYZ(0, 1, 0); this.ez.SetXYZ(0, 0, 1); return this; } SetZero() { this.ex.SetZero(); this.ey.SetZero(); this.ez.SetZero(); return this; } SelfAddM(t) { this.ex.SelfAdd(t.ex); this.ey.SelfAdd(t.ey); this.ez.SelfAdd(t.ez); return this; } Solve33(t, s, i, e) { const r = this.ex.x, h = this.ex.y, n = this.ex.z; const o = this.ey.x, c = this.ey.y, u = this.ey.z; const a = this.ez.x, b = this.ez.y, l = this.ez.z; let S = r * (c * l - u * b) + h * (u * a - o * l) + n * (o * b - c * a); if (S !== 0) { S = 1 / S; } e.x = S * (t * (c * l - u * b) + s * (u * a - o * l) + i * (o * b - c * a)); e.y = S * (r * (s * l - i * b) + h * (i * a - t * l) + n * (t * b - s * a)); e.z = S * (r * (c * i - u * s) + h * (u * t - o * i) + n * (o * s - c * t)); return e; } Solve22(t, s, i) { const e = this.ex.x, r = this.ey.x; const h = this.ex.y, n = this.ey.y; let o = e * n - r * h; if (o !== 0) { o = 1 / o; } i.x = o * (n * t - r * s); i.y = o * (e * s - h * t); return i; } GetInverse22(t) { const s = this.ex.x, i = this.ey.x, e = this.ex.y, r = this.ey.y; let h = s * r - i * e; if (h !== 0) { h = 1 / h; } t.ex.x = h * r; t.ey.x = -h * i; t.ex.z = 0; t.ex.y = -h * e; t.ey.y = h * s; t.ey.z = 0; t.ez.x = 0; t.ez.y = 0; t.ez.z = 0; } GetSymInverse33(t) { let s = b2Vec3.DotV3V3(this.ex, b2Vec3.CrossV3V3(this.ey, this.ez, b2Vec3.s_t0)); if (s !== 0) { s = 1 / s; } const i = this.ex.x, e = this.ey.x, r = this.ez.x; const h = this.ey.y, n = this.ez.y; const o = this.ez.z; t.ex.x = s * (h * o - n * n); t.ex.y = s * (r * n - e * o); t.ex.z = s * (e * n - r * h); t.ey.x = t.ex.y; t.ey.y = s * (i * o - r * r); t.ey.z = s * (r * e - i * n); t.ez.x = t.ex.z; t.ez.y = t.ey.z; t.ez.z = s * (i * h - e * e); } static MulM33V3(t, s, i) { const e = s.x, r = s.y, h = s.z; i.x = t.ex.x * e + t.ey.x * r + t.ez.x * h; i.y = t.ex.y * e + t.ey.y * r + t.ez.y * h; i.z = t.ex.z * e + t.ey.z * r + t.ez.z * h; return i; } static MulM33XYZ(t, s, i, e, r) { r.x = t.ex.x * s + t.ey.x * i + t.ez.x * e; r.y = t.ex.y * s + t.ey.y * i + t.ez.y * e; r.z = t.ex.z * s + t.ey.z * i + t.ez.z * e; return r; } static MulM33V2(t, s, i) { const e = s.x, r = s.y; i.x = t.ex.x * e + t.ey.x * r; i.y = t.ex.y * e + t.ey.y * r; return i; } static MulM33XY(t, s, i, e) { e.x = t.ex.x * s + t.ey.x * i; e.y = t.ex.y * s + t.ey.y * i; return e; } } b2Mat33.IDENTITY = new b2Mat33; export class b2Rot { constructor(t = 0) { this.s = 0; this.c = 1; if (t) { this.s = Math.sin(t); this.c = Math.cos(t); } } Clone() { return (new b2Rot).Copy(this); } Copy(t) { this.s = t.s; this.c = t.c; return this; } SetAngle(t) { this.s = Math.sin(t); this.c = Math.cos(t); return this; } SetIdentity() { this.s = 0; this.c = 1; return this; } GetAngle() { return Math.atan2(this.s, this.c); } GetXAxis(t) { t.x = this.c; t.y = this.s; return t; } GetYAxis(t) { t.x = -this.s; t.y = this.c; return t; } static MulRR(t, s, i) { const e = t.c, r = t.s; const h = s.c, n = s.s; i.s = r * h + e * n; i.c = e * h - r * n; return i; } static MulTRR(t, s, i) { const e = t.c, r = t.s; const h = s.c, n = s.s; i.s = e * n - r * h; i.c = e * h + r * n; return i; } static MulRV(t, s, i) { const e = t.c, r = t.s; const h = s.x, n = s.y; i.x = e * h - r * n; i.y = r * h + e * n; return i; } static MulTRV(t, s, i) { const e = t.c, r = t.s; const h = s.x, n = s.y; i.x = e * h + r * n; i.y = -r * h + e * n; return i; } } b2Rot.IDENTITY = new b2Rot; export class b2Transform { constructor() { this.p = new b2Vec2; this.q = new b2Rot; } Clone() { return (new b2Transform).Copy(this); } Copy(t) { this.p.Copy(t.p); this.q.Copy(t.q); return this; } SetIdentity() { this.p.SetZero(); this.q.SetIdentity(); return this; } SetPositionRotation(t, s) { this.p.Copy(t); this.q.Copy(s); return this; } SetPositionAngle(t, s) { this.p.Copy(t); this.q.SetAngle(s); return this; } SetPosition(t) { this.p.Copy(t); return this; } SetPositionXY(t, s) { this.p.Set(t, s); return this; } SetRotation(t) { this.q.Copy(t); return this; } SetRotationAngle(t) { this.q.SetAngle(t); return this; } GetPosition() { return this.p; } GetRotation() { return this.q; } GetRotationAngle() { return this.q.GetAngle(); } GetAngle() { return this.q.GetAngle(); } static MulXV(t, s, i) { const e = t.q.c, r = t.q.s; const h = s.x, n = s.y; i.x = e * h - r * n + t.p.x; i.y = r * h + e * n + t.p.y; return i; } static MulTXV(t, s, i) { const e = t.q.c, r = t.q.s; const h = s.x - t.p.x; const n = s.y - t.p.y; i.x = e * h + r * n; i.y = -r * h + e * n; return i; } static MulXX(t, s, i) { b2Rot.MulRR(t.q, s.q, i.q); b2Vec2.AddVV(b2Rot.MulRV(t.q, s.p, i.p), t.p, i.p); return i; } static MulTXX(t, s, i) { b2Rot.MulTRR(t.q, s.q, i.q); b2Rot.MulTRV(t.q, b2Vec2.SubVV(s.p, t.p, i.p), i.p); return i; } } b2Transform.IDENTITY = new b2Transform; export class b2Sweep { constructor() { this.localCenter = new b2Vec2; this.c0 = new b2Vec2; this.c = new b2Vec2; this.a0 = 0; this.a = 0; this.alpha0 = 0; } Clone() { return (new b2Sweep).Copy(this); } Copy(t) { this.localCenter.Copy(t.localCenter); this.c0.Copy(t.c0); this.c.Copy(t.c); this.a0 = t.a0; this.a = t.a; this.alpha0 = t.alpha0; return this; } GetTransform(t, s) { t.p.x = (1 - s) * this.c0.x + s * this.c.x; t.p.y = (1 - s) * this.c0.y + s * this.c.y; const i = (1 - s) * this.a0 + s * this.a; t.q.SetAngle(i); t.p.SelfSub(b2Rot.MulRV(t.q, this.localCenter, b2Vec2.s_t0)); return t; } Advance(t) { const s = (t - this.alpha0) / (1 - this.alpha0); const i = 1 - s; this.c0.x = i * this.c0.x + s * this.c.x; this.c0.y = i * this.c0.y + s * this.c.y; this.a0 = i * this.a0 + s * this.a; this.alpha0 = t; } Normalize() { const t = b2_two_pi * Math.floor(this.a0 / b2_two_pi); this.a0 -= t; this.a -= t; } }