lingo3d-react
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
1,330 lines • 69.2 kB
JavaScript
import { V as te, a as U, C as _e, E as b, L as Ke, b as We, F as Ye, T as $e, R as we, c as xe, d as Ie, M as Te, e as _, f as Q, g as Ze, h as I, G as Pe, B as Ae, P as ee, O as se, i as qe, j as He, k as Le, l as E, S as Qe, D as Ne, m as Je, n as et, o as tt, p as nt, q as rt, A as it, r as ae, s as K, U as st, t as at, u as ot, v as lt, Q as N, w as ct, N as pt, x as ut, y as ft, z as ht, H as mt } from "./index-895cfa2f.mjs";
import { p as dt, c as gt } from "./processChildren-cb5144fc.mjs";
import "react";
import "react-dom";
/*!
fflate - fast JavaScript compression/decompression
<https://101arrowz.github.io/fflate>
Licensed under MIT. https://github.com/101arrowz/fflate/blob/master/LICENSE
version 0.6.9
*/
var De = function(c) {
return URL.createObjectURL(new Blob([c], { type: "text/javascript" }));
};
try {
URL.revokeObjectURL(De(""));
} catch {
De = function(e) {
return "data:application/javascript;charset=UTF-8," + encodeURI(e);
};
}
var M = Uint8Array, V = Uint16Array, ue = Uint32Array, Me = new M([
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
2,
2,
2,
2,
3,
3,
3,
3,
4,
4,
4,
4,
5,
5,
5,
5,
0,
/* unused */
0,
0,
/* impossible */
0
]), Se = new M([
0,
0,
0,
0,
1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
6,
7,
7,
8,
8,
9,
9,
10,
10,
11,
11,
12,
12,
13,
13,
/* unused */
0,
0
]), yt = new M([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]), Oe = function(c, e) {
for (var t = new V(31), n = 0; n < 31; ++n)
t[n] = e += 1 << c[n - 1];
for (var r = new ue(t[30]), n = 1; n < 30; ++n)
for (var i = t[n]; i < t[n + 1]; ++i)
r[i] = i - t[n] << 5 | n;
return [t, r];
}, Ee = Oe(Me, 2), Be = Ee[0], vt = Ee[1];
Be[28] = 258, vt[258] = 28;
var wt = Oe(Se, 0), xt = wt[0], fe = new V(32768);
for (var w = 0; w < 32768; ++w) {
var R = (w & 43690) >>> 1 | (w & 21845) << 1;
R = (R & 52428) >>> 2 | (R & 13107) << 2, R = (R & 61680) >>> 4 | (R & 3855) << 4, fe[w] = ((R & 65280) >>> 8 | (R & 255) << 8) >>> 1;
}
var Z = function(c, e, t) {
for (var n = c.length, r = 0, i = new V(e); r < n; ++r)
++i[c[r] - 1];
var s = new V(e);
for (r = 0; r < e; ++r)
s[r] = s[r - 1] + i[r - 1] << 1;
var a;
if (t) {
a = new V(1 << e);
var o = 15 - e;
for (r = 0; r < n; ++r)
if (c[r])
for (var p = r << 4 | c[r], u = e - c[r], l = s[c[r] - 1]++ << u, f = l | (1 << u) - 1; l <= f; ++l)
a[fe[l] >>> o] = p;
} else
for (a = new V(n), r = 0; r < n; ++r)
c[r] && (a[r] = fe[s[c[r] - 1]++] >>> 15 - c[r]);
return a;
}, q = new M(288);
for (var w = 0; w < 144; ++w)
q[w] = 8;
for (var w = 144; w < 256; ++w)
q[w] = 9;
for (var w = 256; w < 280; ++w)
q[w] = 7;
for (var w = 280; w < 288; ++w)
q[w] = 8;
var Re = new M(32);
for (var w = 0; w < 32; ++w)
Re[w] = 5;
var It = /* @__PURE__ */ Z(q, 9, 1), Tt = /* @__PURE__ */ Z(Re, 5, 1), oe = function(c) {
for (var e = c[0], t = 1; t < c.length; ++t)
c[t] > e && (e = c[t]);
return e;
}, O = function(c, e, t) {
var n = e / 8 | 0;
return (c[n] | c[n + 1] << 8) >> (e & 7) & t;
}, le = function(c, e) {
var t = e / 8 | 0;
return (c[t] | c[t + 1] << 8 | c[t + 2] << 16) >> (e & 7);
}, Pt = function(c) {
return (c / 8 | 0) + (c & 7 && 1);
}, At = function(c, e, t) {
(e == null || e < 0) && (e = 0), (t == null || t > c.length) && (t = c.length);
var n = new (c instanceof V ? V : c instanceof ue ? ue : M)(t - e);
return n.set(c.subarray(e, t)), n;
}, Lt = function(c, e, t) {
var n = c.length;
if (!n || t && !t.l && n < 5)
return e || new M(0);
var r = !e || t, i = !t || t.i;
t || (t = {}), e || (e = new M(n * 3));
var s = function(ge) {
var ye = e.length;
if (ge > ye) {
var ve = new M(Math.max(ye * 2, ge));
ve.set(e), e = ve;
}
}, a = t.f || 0, o = t.p || 0, p = t.b || 0, u = t.l, l = t.d, f = t.m, h = t.n, m = n * 8;
do {
if (!u) {
t.f = a = O(c, o, 1);
var d = O(c, o + 1, 3);
if (o += 3, d)
if (d == 1)
u = It, l = Tt, f = 9, h = 5;
else if (d == 2) {
var y = O(c, o, 31) + 257, L = O(c, o + 10, 15) + 4, S = y + O(c, o + 5, 31) + 1;
o += 14;
for (var A = new M(S), C = new M(19), D = 0; D < L; ++D)
C[yt[D]] = O(c, o + D * 3, 7);
o += L * 3;
for (var X = oe(C), F = (1 << X) - 1, Y = Z(C, X, 1), D = 0; D < S; ) {
var j = Y[O(c, o, F)];
o += j & 15;
var v = j >>> 4;
if (v < 16)
A[D++] = v;
else {
var G = 0, H = 0;
for (v == 16 ? (H = 3 + O(c, o, 3), o += 2, G = A[D - 1]) : v == 17 ? (H = 3 + O(c, o, 7), o += 3) : v == 18 && (H = 11 + O(c, o, 127), o += 7); H--; )
A[D++] = G;
}
}
var he = A.subarray(0, y), B = A.subarray(y);
f = oe(he), h = oe(B), u = Z(he, f, 1), l = Z(B, h, 1);
} else
throw "invalid block type";
else {
var v = Pt(o) + 4, P = c[v - 4] | c[v - 3] << 8, x = v + P;
if (x > n) {
if (i)
throw "unexpected EOF";
break;
}
r && s(p + P), e.set(c.subarray(v, x), p), t.b = p += P, t.p = o = x * 8;
continue;
}
if (o > m) {
if (i)
throw "unexpected EOF";
break;
}
}
r && s(p + 131072);
for (var Ge = (1 << f) - 1, ze = (1 << h) - 1, ne = o; ; ne = o) {
var G = u[le(c, o) & Ge], z = G >>> 4;
if (o += G & 15, o > m) {
if (i)
throw "unexpected EOF";
break;
}
if (!G)
throw "invalid length/literal";
if (z < 256)
e[p++] = z;
else if (z == 256) {
ne = o, u = null;
break;
} else {
var me = z - 254;
if (z > 264) {
var D = z - 257, $ = Me[D];
me = O(c, o, (1 << $) - 1) + Be[D], o += $;
}
var re = l[le(c, o) & ze], ie = re >>> 4;
if (!re)
throw "invalid distance";
o += re & 15;
var B = xt[ie];
if (ie > 3) {
var $ = Se[ie];
B += le(c, o) & (1 << $) - 1, o += $;
}
if (o > m) {
if (i)
throw "unexpected EOF";
break;
}
r && s(p + 131072);
for (var de = p + me; p < de; p += 4)
e[p] = e[p - B], e[p + 1] = e[p + 1 - B], e[p + 2] = e[p + 2 - B], e[p + 3] = e[p + 3 - B];
p = de;
}
}
t.l = u, t.p = ne, t.b = p, u && (a = 1, t.m = f, t.d = l, t.n = h);
} while (!a);
return p == e.length ? e : At(e, 0, p);
}, Dt = /* @__PURE__ */ new M(0), Ft = function(c) {
if ((c[0] & 15) != 8 || c[0] >>> 4 > 7 || (c[0] << 8 | c[1]) % 31)
throw "invalid zlib data";
if (c[1] & 32)
throw "invalid zlib data: preset dictionaries not supported";
};
function kt(c, e) {
return Lt((Ft(c), c.subarray(2, -4)), e);
}
var Ct = typeof TextDecoder < "u" && /* @__PURE__ */ new TextDecoder(), Mt = 0;
try {
Ct.decode(Dt, { stream: !0 }), Mt = 1;
} catch {
}
function be(c, e, t) {
const n = t.length - c - 1;
if (e >= t[n])
return n - 1;
if (e <= t[c])
return c;
let r = c, i = n, s = Math.floor((r + i) / 2);
for (; e < t[s] || e >= t[s + 1]; )
e < t[s] ? i = s : r = s, s = Math.floor((r + i) / 2);
return s;
}
function St(c, e, t, n) {
const r = [], i = [], s = [];
r[0] = 1;
for (let a = 1; a <= t; ++a) {
i[a] = e - n[c + 1 - a], s[a] = n[c + a] - e;
let o = 0;
for (let p = 0; p < a; ++p) {
const u = s[p + 1], l = i[a - p], f = r[p] / (u + l);
r[p] = o + u * f, o = l * f;
}
r[a] = o;
}
return r;
}
function Ot(c, e, t, n) {
const r = be(c, n, e), i = St(r, n, c, e), s = new te(0, 0, 0, 0);
for (let a = 0; a <= c; ++a) {
const o = t[r - c + a], p = i[a], u = o.w * p;
s.x += o.x * u, s.y += o.y * u, s.z += o.z * u, s.w += o.w * p;
}
return s;
}
function Et(c, e, t, n, r) {
const i = [];
for (let l = 0; l <= t; ++l)
i[l] = 0;
const s = [];
for (let l = 0; l <= n; ++l)
s[l] = i.slice(0);
const a = [];
for (let l = 0; l <= t; ++l)
a[l] = i.slice(0);
a[0][0] = 1;
const o = i.slice(0), p = i.slice(0);
for (let l = 1; l <= t; ++l) {
o[l] = e - r[c + 1 - l], p[l] = r[c + l] - e;
let f = 0;
for (let h = 0; h < l; ++h) {
const m = p[h + 1], d = o[l - h];
a[l][h] = m + d;
const v = a[h][l - 1] / a[l][h];
a[h][l] = f + m * v, f = d * v;
}
a[l][l] = f;
}
for (let l = 0; l <= t; ++l)
s[0][l] = a[l][t];
for (let l = 0; l <= t; ++l) {
let f = 0, h = 1;
const m = [];
for (let d = 0; d <= t; ++d)
m[d] = i.slice(0);
m[0][0] = 1;
for (let d = 1; d <= n; ++d) {
let v = 0;
const P = l - d, x = t - d;
l >= d && (m[h][0] = m[f][0] / a[x + 1][P], v = m[h][0] * a[P][x]);
const y = P >= -1 ? 1 : -P, L = l - 1 <= x ? d - 1 : t - l;
for (let A = y; A <= L; ++A)
m[h][A] = (m[f][A] - m[f][A - 1]) / a[x + 1][P + A], v += m[h][A] * a[P + A][x];
l <= x && (m[h][d] = -m[f][d - 1] / a[x + 1][l], v += m[h][d] * a[l][x]), s[d][l] = v;
const S = f;
f = h, h = S;
}
}
let u = t;
for (let l = 1; l <= n; ++l) {
for (let f = 0; f <= t; ++f)
s[l][f] *= u;
u *= t - l;
}
return s;
}
function Bt(c, e, t, n, r) {
const i = r < c ? r : c, s = [], a = be(c, n, e), o = Et(a, n, c, i, e), p = [];
for (let u = 0; u < t.length; ++u) {
const l = t[u].clone(), f = l.w;
l.x *= f, l.y *= f, l.z *= f, p[u] = l;
}
for (let u = 0; u <= i; ++u) {
const l = p[a - c].clone().multiplyScalar(o[u][0]);
for (let f = 1; f <= c; ++f)
l.add(p[a - c + f].clone().multiplyScalar(o[u][f]));
s[u] = l;
}
for (let u = i + 1; u <= r + 1; ++u)
s[u] = new te(0, 0, 0);
return s;
}
function Rt(c, e) {
let t = 1;
for (let r = 2; r <= c; ++r)
t *= r;
let n = 1;
for (let r = 2; r <= e; ++r)
n *= r;
for (let r = 2; r <= c - e; ++r)
n *= r;
return t / n;
}
function bt(c) {
const e = c.length, t = [], n = [];
for (let i = 0; i < e; ++i) {
const s = c[i];
t[i] = new U(s.x, s.y, s.z), n[i] = s.w;
}
const r = [];
for (let i = 0; i < e; ++i) {
const s = t[i].clone();
for (let a = 1; a <= i; ++a)
s.sub(r[i - a].clone().multiplyScalar(Rt(i, a) * n[a]));
r[i] = s.divideScalar(n[0]);
}
return r;
}
function Vt(c, e, t, n, r) {
const i = Bt(c, e, t, n, r);
return bt(i);
}
class Ut extends _e {
constructor(e, t, n, r, i) {
super(), this.degree = e, this.knots = t, this.controlPoints = [], this.startKnot = r || 0, this.endKnot = i || this.knots.length - 1;
for (let s = 0; s < n.length; ++s) {
const a = n[s];
this.controlPoints[s] = new te(a.x, a.y, a.z, a.w);
}
}
getPoint(e, t = new U()) {
const n = t, r = this.knots[this.startKnot] + e * (this.knots[this.endKnot] - this.knots[this.startKnot]), i = Ot(this.degree, this.knots, this.controlPoints, r);
return i.w !== 1 && i.divideScalar(i.w), n.set(i.x, i.y, i.z);
}
getTangent(e, t = new U()) {
const n = t, r = this.knots[0] + e * (this.knots[this.knots.length - 1] - this.knots[0]), i = Vt(this.degree, this.knots, this.controlPoints, r, 1);
return n.copy(i[1]).normalize(), n;
}
}
let g, T, k;
class Xt extends Ke {
constructor(e) {
super(e);
}
load(e, t, n, r) {
const i = this, s = i.path === "" ? We.extractUrlBase(e) : i.path, a = new Ye(this.manager);
a.setPath(i.path), a.setResponseType("arraybuffer"), a.setRequestHeader(i.requestHeader), a.setWithCredentials(i.withCredentials), a.load(e, function(o) {
try {
t(i.parse(o, s));
} catch (p) {
r ? r(p) : console.error(p), i.manager.itemError(e);
}
}, n, r);
}
parse(e, t) {
if (Wt(e))
g = new Kt().parse(e);
else {
const r = je(e);
if (!Yt(r))
throw new Error("FBXLoader: Unknown format.");
if (ke(r) < 7e3)
throw new Error("FBXLoader: FBX version not supported, FileVersion: " + ke(r));
g = new _t().parse(r);
}
const n = new $e(this.manager).setPath(this.resourcePath || t).setCrossOrigin(this.crossOrigin);
return new jt(n, this.manager).parse(g);
}
}
class jt {
constructor(e, t) {
this.textureLoader = e, this.manager = t;
}
parse() {
T = this.parseConnections();
const e = this.parseImages(), t = this.parseTextures(e), n = this.parseMaterials(t), r = this.parseDeformers(), i = new Gt().parse(r);
return this.parseScene(r, i, n), k;
}
// Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry )
// and details the connection type
parseConnections() {
const e = /* @__PURE__ */ new Map();
return "Connections" in g && g.Connections.connections.forEach(function(n) {
const r = n[0], i = n[1], s = n[2];
e.has(r) || e.set(r, {
parents: [],
children: []
});
const a = {
ID: i,
relationship: s
};
e.get(r).parents.push(a), e.has(i) || e.set(i, {
parents: [],
children: []
});
const o = {
ID: r,
relationship: s
};
e.get(i).children.push(o);
}), e;
}
// Parse FBXTree.Objects.Video for embedded image data
// These images are connected to textures in FBXTree.Objects.Textures
// via FBXTree.Connections.
parseImages() {
const e = {}, t = {};
if ("Video" in g.Objects) {
const n = g.Objects.Video;
for (const r in n) {
const i = n[r], s = parseInt(r);
if (e[s] = i.RelativeFilename || i.Filename, "Content" in i) {
const a = i.Content instanceof ArrayBuffer && i.Content.byteLength > 0, o = typeof i.Content == "string" && i.Content !== "";
if (a || o) {
const p = this.parseImage(n[r]);
t[i.RelativeFilename || i.Filename] = p;
}
}
}
}
for (const n in e) {
const r = e[n];
t[r] !== void 0 ? e[n] = t[r] : e[n] = e[n].split("\\").pop();
}
return e;
}
// Parse embedded image data in FBXTree.Video.Content
parseImage(e) {
const t = e.Content, n = e.RelativeFilename || e.Filename, r = n.slice(n.lastIndexOf(".") + 1).toLowerCase();
let i;
switch (r) {
case "bmp":
i = "image/bmp";
break;
case "jpg":
case "jpeg":
i = "image/jpeg";
break;
case "png":
i = "image/png";
break;
case "tif":
i = "image/tiff";
break;
case "tga":
this.manager.getHandler(".tga") === null && console.warn("FBXLoader: TGA loader not found, skipping ", n), i = "image/tga";
break;
default:
console.warn('FBXLoader: Image type "' + r + '" is not supported.');
return;
}
if (typeof t == "string")
return "data:" + i + ";base64," + t;
{
const s = new Uint8Array(t);
return window.URL.createObjectURL(new Blob([s], { type: i }));
}
}
// Parse nodes in FBXTree.Objects.Texture
// These contain details such as UV scaling, cropping, rotation etc and are connected
// to images in FBXTree.Objects.Video
parseTextures(e) {
const t = /* @__PURE__ */ new Map();
if ("Texture" in g.Objects) {
const n = g.Objects.Texture;
for (const r in n) {
const i = this.parseTexture(n[r], e);
t.set(parseInt(r), i);
}
}
return t;
}
// Parse individual node in FBXTree.Objects.Texture
parseTexture(e, t) {
const n = this.loadTexture(e, t);
n.ID = e.id, n.name = e.attrName;
const r = e.WrapModeU, i = e.WrapModeV, s = r !== void 0 ? r.value : 0, a = i !== void 0 ? i.value : 0;
if (n.wrapS = s === 0 ? we : xe, n.wrapT = a === 0 ? we : xe, "Scaling" in e) {
const o = e.Scaling.value;
n.repeat.x = o[0], n.repeat.y = o[1];
}
if ("Translation" in e) {
const o = e.Translation.value;
n.offset.x = o[0], n.offset.y = o[1];
}
return n;
}
// load a texture specified as a blob or data URI, or via an external URL using TextureLoader
loadTexture(e, t) {
let n;
const r = this.textureLoader.path, i = T.get(e.id).children;
i !== void 0 && i.length > 0 && t[i[0].ID] !== void 0 && (n = t[i[0].ID], (n.indexOf("blob:") === 0 || n.indexOf("data:") === 0) && this.textureLoader.setPath(void 0));
let s;
const a = e.FileName.slice(-3).toLowerCase();
if (a === "tga") {
const o = this.manager.getHandler(".tga");
o === null ? (console.warn("FBXLoader: TGA loader not found, creating placeholder texture for", e.RelativeFilename), s = new Ie()) : (o.setPath(this.textureLoader.path), s = o.load(n));
} else
a === "psd" ? (console.warn("FBXLoader: PSD textures are not supported, creating placeholder texture for", e.RelativeFilename), s = new Ie()) : s = this.textureLoader.load(n);
return this.textureLoader.setPath(r), s;
}
// Parse nodes in FBXTree.Objects.Material
parseMaterials(e) {
const t = /* @__PURE__ */ new Map();
if ("Material" in g.Objects) {
const n = g.Objects.Material;
for (const r in n) {
const i = this.parseMaterial(n[r], e);
i !== null && t.set(parseInt(r), i);
}
}
return t;
}
// Parse single node in FBXTree.Objects.Material
// Materials are connected to texture maps in FBXTree.Objects.Textures
// FBX format currently only supports Lambert and Phong shading models
parseMaterial(e, t) {
const n = e.id, r = e.attrName;
let i = e.ShadingModel;
if (typeof i == "object" && (i = i.value), !T.has(n))
return null;
const s = this.parseParameters(e, t, n), a = new Te();
return a.setValues(s), a.name = r, a;
}
// Parse FBX material and return parameters suitable for a three.js material
// Also parse the texture map and return any textures associated with the material
parseParameters(e, t, n) {
const r = {};
e.BumpFactor && (r.bumpScale = e.BumpFactor.value), e.Diffuse ? r.color = new _().fromArray(e.Diffuse.value) : e.DiffuseColor && (e.DiffuseColor.type === "Color" || e.DiffuseColor.type === "ColorRGB") && (r.color = new _().fromArray(e.DiffuseColor.value)), e.DisplacementFactor && (r.displacementScale = e.DisplacementFactor.value), e.Emissive ? r.emissive = new _().fromArray(e.Emissive.value) : e.EmissiveColor && (e.EmissiveColor.type === "Color" || e.EmissiveColor.type === "ColorRGB") && (r.emissive = new _().fromArray(e.EmissiveColor.value)), e.EmissiveFactor && (r.emissiveIntensity = parseFloat(e.EmissiveFactor.value)), e.Opacity && (r.opacity = parseFloat(e.Opacity.value)), r.opacity < 1 && (r.transparent = !0);
const i = this;
return T.get(n).children.forEach(function(s) {
const a = s.relationship;
switch (a) {
case "Bump":
r.bumpMap = i.getTexture(t, s.ID);
break;
case "Maya|TEX_ao_map":
r.aoMap = i.getTexture(t, s.ID);
break;
case "DiffuseColor":
case "Maya|TEX_color_map":
r.map = i.getTexture(t, s.ID), r.map !== void 0 && (r.map.encoding = Q);
break;
case "DisplacementColor":
r.displacementMap = i.getTexture(t, s.ID);
break;
case "EmissiveColor":
r.emissiveMap = i.getTexture(t, s.ID), r.emissiveMap !== void 0 && (r.emissiveMap.encoding = Q);
break;
case "NormalMap":
case "Maya|TEX_normal_map":
r.normalMap = i.getTexture(t, s.ID);
break;
case "ReflectionColor":
r.envMap = i.getTexture(t, s.ID), r.envMap !== void 0 && (r.envMap.mapping = Ze, r.envMap.encoding = Q);
break;
case "SpecularColor":
r.specularMap = i.getTexture(t, s.ID), r.specularMap !== void 0 && (r.specularMap.encoding = Q);
break;
case "TransparentColor":
case "TransparencyFactor":
r.alphaMap = i.getTexture(t, s.ID), r.transparent = !0;
break;
case "AmbientColor":
case "ShininessExponent":
case "SpecularFactor":
case "VectorDisplacementColor":
default:
console.warn("FBXLoader: %s map is not supported, skipping texture.", a);
break;
}
}), r;
}
// get a texture from the textureMap for use by a material.
getTexture(e, t) {
return "LayeredTexture" in g.Objects && t in g.Objects.LayeredTexture && (console.warn("FBXLoader: layered textures are not supported. Discarding all but first layer."), t = T.get(t).children[0].ID), e.get(t);
}
// Parse nodes in FBXTree.Objects.Deformer
// Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here
// Generates map of Skeleton-like objects for use later when generating and binding skeletons.
parseDeformers() {
const e = {}, t = {};
if ("Deformer" in g.Objects) {
const n = g.Objects.Deformer;
for (const r in n) {
const i = n[r], s = T.get(parseInt(r));
if (i.attrType === "Skin") {
const a = this.parseSkeleton(s, n);
a.ID = r, s.parents.length > 1 && console.warn("FBXLoader: skeleton attached to more than one geometry is not supported."), a.geometryID = s.parents[0].ID, e[r] = a;
} else if (i.attrType === "BlendShape") {
const a = {
id: r
};
a.rawTargets = this.parseMorphTargets(s, n), a.id = r, s.parents.length > 1 && console.warn("FBXLoader: morph target attached to more than one geometry is not supported."), t[r] = a;
}
}
}
return {
skeletons: e,
morphTargets: t
};
}
// Parse single nodes in FBXTree.Objects.Deformer
// The top level skeleton node has type 'Skin' and sub nodes have type 'Cluster'
// Each skin node represents a skeleton and each cluster node represents a bone
parseSkeleton(e, t) {
const n = [];
return e.children.forEach(function(r) {
const i = t[r.ID];
if (i.attrType !== "Cluster")
return;
const s = {
ID: r.ID,
indices: [],
weights: [],
transformLink: new I().fromArray(i.TransformLink.a)
// transform: new Matrix4().fromArray( boneNode.Transform.a ),
// linkMode: boneNode.Mode,
};
"Indexes" in i && (s.indices = i.Indexes.a, s.weights = i.Weights.a), n.push(s);
}), {
rawBones: n,
bones: []
};
}
// The top level morph deformer node has type "BlendShape" and sub nodes have type "BlendShapeChannel"
parseMorphTargets(e, t) {
const n = [];
for (let r = 0; r < e.children.length; r++) {
const i = e.children[r], s = t[i.ID], a = {
name: s.attrName,
initialWeight: s.DeformPercent,
id: s.id,
fullWeights: s.FullWeights.a
};
if (s.attrType !== "BlendShapeChannel")
return;
a.geoID = T.get(parseInt(i.ID)).children.filter(function(o) {
return o.relationship === void 0;
})[0].ID, n.push(a);
}
return n;
}
// create the main Group() to be returned by the loader
parseScene(e, t, n) {
k = new Pe();
const r = this.parseModels(e.skeletons, t, n), i = g.Objects.Model, s = this;
r.forEach(function(o) {
const p = i[o.ID];
s.setLookAtProperties(o, p), T.get(o.ID).parents.forEach(function(l) {
const f = r.get(l.ID);
f !== void 0 && f.add(o);
}), o.parent === null && k.add(o);
}), this.bindSkeleton(e.skeletons, t, r), this.createAmbientLight(), k.traverse(function(o) {
if (o.userData.transformData) {
o.parent && (o.userData.transformData.parentMatrix = o.parent.matrix, o.userData.transformData.parentMatrixWorld = o.parent.matrixWorld);
const p = Ue(o.userData.transformData);
o.applyMatrix4(p), o.updateWorldMatrix();
}
});
const a = new zt().parse();
k.children.length === 1 && k.children[0].isGroup && (k.children[0].animations = a, k = k.children[0]), k.animations = a;
}
// parse nodes in FBXTree.Objects.Model
parseModels(e, t, n) {
const r = /* @__PURE__ */ new Map(), i = g.Objects.Model;
for (const s in i) {
const a = parseInt(s), o = i[s], p = T.get(a);
let u = this.buildSkeleton(p, e, a, o.attrName);
if (!u) {
switch (o.attrType) {
case "Camera":
u = this.createCamera(p);
break;
case "Light":
u = this.createLight(p);
break;
case "Mesh":
u = this.createMesh(p, t, n);
break;
case "NurbsCurve":
u = this.createCurve(p, t);
break;
case "LimbNode":
case "Root":
u = new Ae();
break;
case "Null":
default:
u = new Pe();
break;
}
u.name = o.attrName ? ee.sanitizeNodeName(o.attrName) : "", u.ID = a;
}
this.getTransformData(u, o), r.set(a, u);
}
return r;
}
buildSkeleton(e, t, n, r) {
let i = null;
return e.parents.forEach(function(s) {
for (const a in t) {
const o = t[a];
o.rawBones.forEach(function(p, u) {
if (p.ID === s.ID) {
const l = i;
i = new Ae(), i.matrixWorld.copy(p.transformLink), i.name = r ? ee.sanitizeNodeName(r) : "", i.ID = n, o.bones[u] = i, l !== null && i.add(l);
}
});
}
}), i;
}
// create a PerspectiveCamera or OrthographicCamera
createCamera(e) {
let t, n;
if (e.children.forEach(function(r) {
const i = g.Objects.NodeAttribute[r.ID];
i !== void 0 && (n = i);
}), n === void 0)
t = new se();
else {
let r = 0;
n.CameraProjectionType !== void 0 && n.CameraProjectionType.value === 1 && (r = 1);
let i = 1;
n.NearPlane !== void 0 && (i = n.NearPlane.value / 1e3);
let s = 1e3;
n.FarPlane !== void 0 && (s = n.FarPlane.value / 1e3);
let a = window.innerWidth, o = window.innerHeight;
n.AspectWidth !== void 0 && n.AspectHeight !== void 0 && (a = n.AspectWidth.value, o = n.AspectHeight.value);
const p = a / o;
let u = 45;
n.FieldOfView !== void 0 && (u = n.FieldOfView.value);
const l = n.FocalLength ? n.FocalLength.value : null;
switch (r) {
case 0:
t = new He(u, p, i, s), l !== null && t.setFocalLength(l);
break;
case 1:
t = new qe(-a / 2, a / 2, o / 2, -o / 2, i, s);
break;
default:
console.warn("FBXLoader: Unknown camera type " + r + "."), t = new se();
break;
}
}
return t;
}
// Create a DirectionalLight, PointLight or SpotLight
createLight(e) {
let t, n;
if (e.children.forEach(function(r) {
const i = g.Objects.NodeAttribute[r.ID];
i !== void 0 && (n = i);
}), n === void 0)
t = new se();
else {
let r;
n.LightType === void 0 ? r = 0 : r = n.LightType.value;
let i = 16777215;
n.Color !== void 0 && (i = new _().fromArray(n.Color.value));
let s = n.Intensity === void 0 ? 1 : n.Intensity.value / 100;
n.CastLightOnObject !== void 0 && n.CastLightOnObject.value === 0 && (s = 0);
let a = 0;
n.FarAttenuationEnd !== void 0 && (n.EnableFarAttenuation !== void 0 && n.EnableFarAttenuation.value === 0 ? a = 0 : a = n.FarAttenuationEnd.value);
const o = 1;
switch (r) {
case 0:
t = new Le(i, s, a, o);
break;
case 1:
t = new Ne(i, s);
break;
case 2:
let p = Math.PI / 3;
n.InnerAngle !== void 0 && (p = E.degToRad(n.InnerAngle.value));
let u = 0;
n.OuterAngle !== void 0 && (u = E.degToRad(n.OuterAngle.value), u = Math.max(u, 1)), t = new Qe(i, s, a, p, u, o);
break;
default:
console.warn("FBXLoader: Unknown light type " + n.LightType.value + ", defaulting to a PointLight."), t = new Le(i, s);
break;
}
n.CastShadows !== void 0 && n.CastShadows.value === 1 && (t.castShadow = !0);
}
return t;
}
createMesh(e, t, n) {
let r, i = null, s = null;
const a = [];
return e.children.forEach(function(o) {
t.has(o.ID) && (i = t.get(o.ID)), n.has(o.ID) && a.push(n.get(o.ID));
}), a.length > 1 ? s = a : a.length > 0 ? s = a[0] : (s = new Te({ color: 13421772 }), a.push(s)), "color" in i.attributes && a.forEach(function(o) {
o.vertexColors = !0;
}), i.FBX_Deformer ? (r = new Je(i, s), r.normalizeSkinWeights()) : r = new et(i, s), r;
}
createCurve(e, t) {
const n = e.children.reduce(function(i, s) {
return t.has(s.ID) && (i = t.get(s.ID)), i;
}, null), r = new tt({
color: 3342591,
linewidth: 1
});
return new nt(n, r);
}
// parse the model node for transform data
getTransformData(e, t) {
const n = {};
"InheritType" in t && (n.inheritType = parseInt(t.InheritType.value)), "RotationOrder" in t ? n.eulerOrder = Xe(t.RotationOrder.value) : n.eulerOrder = "ZYX", "Lcl_Translation" in t && (n.translation = t.Lcl_Translation.value), "PreRotation" in t && (n.preRotation = t.PreRotation.value), "Lcl_Rotation" in t && (n.rotation = t.Lcl_Rotation.value), "PostRotation" in t && (n.postRotation = t.PostRotation.value), "Lcl_Scaling" in t && (n.scale = t.Lcl_Scaling.value), "ScalingOffset" in t && (n.scalingOffset = t.ScalingOffset.value), "ScalingPivot" in t && (n.scalingPivot = t.ScalingPivot.value), "RotationOffset" in t && (n.rotationOffset = t.RotationOffset.value), "RotationPivot" in t && (n.rotationPivot = t.RotationPivot.value), e.userData.transformData = n;
}
setLookAtProperties(e, t) {
"LookAtProperty" in t && T.get(e.ID).children.forEach(function(r) {
if (r.relationship === "LookAtProperty") {
const i = g.Objects.Model[r.ID];
if ("Lcl_Translation" in i) {
const s = i.Lcl_Translation.value;
e.target !== void 0 ? (e.target.position.fromArray(s), k.add(e.target)) : e.lookAt(new U().fromArray(s));
}
}
});
}
bindSkeleton(e, t, n) {
const r = this.parsePoseNodes();
for (const i in e) {
const s = e[i];
T.get(parseInt(s.ID)).parents.forEach(function(o) {
if (t.has(o.ID)) {
const p = o.ID;
T.get(p).parents.forEach(function(l) {
n.has(l.ID) && n.get(l.ID).bind(new rt(s.bones), r[l.ID]);
});
}
});
}
}
parsePoseNodes() {
const e = {};
if ("Pose" in g.Objects) {
const t = g.Objects.Pose;
for (const n in t)
if (t[n].attrType === "BindPose" && t[n].NbPoseNodes > 0) {
const r = t[n].PoseNode;
Array.isArray(r) ? r.forEach(function(i) {
e[i.Node] = new I().fromArray(i.Matrix.a);
}) : e[r.Node] = new I().fromArray(r.Matrix.a);
}
}
return e;
}
// Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light
createAmbientLight() {
if ("GlobalSettings" in g && "AmbientColor" in g.GlobalSettings) {
const e = g.GlobalSettings.AmbientColor.value, t = e[0], n = e[1], r = e[2];
if (t !== 0 || n !== 0 || r !== 0) {
const i = new _(t, n, r);
k.add(new it(i, 1));
}
}
}
}
class Gt {
constructor() {
this.negativeMaterialIndices = !1;
}
// Parse nodes in FBXTree.Objects.Geometry
parse(e) {
const t = /* @__PURE__ */ new Map();
if ("Geometry" in g.Objects) {
const n = g.Objects.Geometry;
for (const r in n) {
const i = T.get(parseInt(r)), s = this.parseGeometry(i, n[r], e);
t.set(parseInt(r), s);
}
}
return this.negativeMaterialIndices === !0 && console.warn("FBXLoader: The FBX file contains invalid (negative) material indices. The asset might not render as expected."), t;
}
// Parse single node in FBXTree.Objects.Geometry
parseGeometry(e, t, n) {
switch (t.attrType) {
case "Mesh":
return this.parseMeshGeometry(e, t, n);
case "NurbsCurve":
return this.parseNurbsGeometry(t);
}
}
// Parse single node mesh geometry in FBXTree.Objects.Geometry
parseMeshGeometry(e, t, n) {
const r = n.skeletons, i = [], s = e.parents.map(function(l) {
return g.Objects.Model[l.ID];
});
if (s.length === 0)
return;
const a = e.children.reduce(function(l, f) {
return r[f.ID] !== void 0 && (l = r[f.ID]), l;
}, null);
e.children.forEach(function(l) {
n.morphTargets[l.ID] !== void 0 && i.push(n.morphTargets[l.ID]);
});
const o = s[0], p = {};
"RotationOrder" in o && (p.eulerOrder = Xe(o.RotationOrder.value)), "InheritType" in o && (p.inheritType = parseInt(o.InheritType.value)), "GeometricTranslation" in o && (p.translation = o.GeometricTranslation.value), "GeometricRotation" in o && (p.rotation = o.GeometricRotation.value), "GeometricScaling" in o && (p.scale = o.GeometricScaling.value);
const u = Ue(p);
return this.genGeometry(t, a, i, u);
}
// Generate a BufferGeometry from a node in FBXTree.Objects.Geometry
genGeometry(e, t, n, r) {
const i = new ae();
e.attrName && (i.name = e.attrName);
const s = this.parseGeoNode(e, t), a = this.genBuffers(s), o = new K(a.vertex, 3);
if (o.applyMatrix4(r), i.setAttribute("position", o), a.colors.length > 0 && i.setAttribute("color", new K(a.colors, 3)), t && (i.setAttribute("skinIndex", new st(a.weightsIndices, 4)), i.setAttribute("skinWeight", new K(a.vertexWeights, 4)), i.FBX_Deformer = t), a.normal.length > 0) {
const p = new at().getNormalMatrix(r), u = new K(a.normal, 3);
u.applyNormalMatrix(p), i.setAttribute("normal", u);
}
if (a.uvs.forEach(function(p, u) {
let l = "uv" + (u + 1).toString();
u === 0 && (l = "uv"), i.setAttribute(l, new K(a.uvs[u], 2));
}), s.material && s.material.mappingType !== "AllSame") {
let p = a.materialIndex[0], u = 0;
if (a.materialIndex.forEach(function(l, f) {
l !== p && (i.addGroup(u, f - u, p), p = l, u = f);
}), i.groups.length > 0) {
const l = i.groups[i.groups.length - 1], f = l.start + l.count;
f !== a.materialIndex.length && i.addGroup(f, a.materialIndex.length - f, p);
}
i.groups.length === 0 && i.addGroup(0, a.materialIndex.length, a.materialIndex[0]);
}
return this.addMorphTargets(i, e, n, r), i;
}
parseGeoNode(e, t) {
const n = {};
if (n.vertexPositions = e.Vertices !== void 0 ? e.Vertices.a : [], n.vertexIndices = e.PolygonVertexIndex !== void 0 ? e.PolygonVertexIndex.a : [], e.LayerElementColor && (n.color = this.parseVertexColors(e.LayerElementColor[0])), e.LayerElementMaterial && (n.material = this.parseMaterialIndices(e.LayerElementMaterial[0])), e.LayerElementNormal && (n.normal = this.parseNormals(e.LayerElementNormal[0])), e.LayerElementUV) {
n.uv = [];
let r = 0;
for (; e.LayerElementUV[r]; )
e.LayerElementUV[r].UV && n.uv.push(this.parseUVs(e.LayerElementUV[r])), r++;
}
return n.weightTable = {}, t !== null && (n.skeleton = t, t.rawBones.forEach(function(r, i) {
r.indices.forEach(function(s, a) {
n.weightTable[s] === void 0 && (n.weightTable[s] = []), n.weightTable[s].push({
id: i,
weight: r.weights[a]
});
});
})), n;
}
genBuffers(e) {
const t = {
vertex: [],
normal: [],
colors: [],
uvs: [],
materialIndex: [],
vertexWeights: [],
weightsIndices: []
};
let n = 0, r = 0, i = !1, s = [], a = [], o = [], p = [], u = [], l = [];
const f = this;
return e.vertexIndices.forEach(function(h, m) {
let d, v = !1;
h < 0 && (h = h ^ -1, v = !0);
let P = [], x = [];
if (s.push(h * 3, h * 3 + 1, h * 3 + 2), e.color) {
const y = J(m, n, h, e.color);
o.push(y[0], y[1], y[2]);
}
if (e.skeleton) {
if (e.weightTable[h] !== void 0 && e.weightTable[h].forEach(function(y) {
x.push(y.weight), P.push(y.id);
}), x.length > 4) {
i || (console.warn("FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights."), i = !0);
const y = [0, 0, 0, 0], L = [0, 0, 0, 0];
x.forEach(function(S, A) {
let C = S, D = P[A];
L.forEach(function(X, F, Y) {
if (C > X) {
Y[F] = C, C = X;
const j = y[F];
y[F] = D, D = j;
}
});
}), P = y, x = L;
}
for (; x.length < 4; )
x.push(0), P.push(0);
for (let y = 0; y < 4; ++y)
u.push(x[y]), l.push(P[y]);
}
if (e.normal) {
const y = J(m, n, h, e.normal);
a.push(y[0], y[1], y[2]);
}
e.material && e.material.mappingType !== "AllSame" && (d = J(m, n, h, e.material)[0], d < 0 && (f.negativeMaterialIndices = !0, d = 0)), e.uv && e.uv.forEach(function(y, L) {
const S = J(m, n, h, y);
p[L] === void 0 && (p[L] = []), p[L].push(S[0]), p[L].push(S[1]);
}), r++, v && (r > 4 && console.warn("FBXLoader: Polygons with more than four sides are not supported. Make sure to triangulate the geometry during export."), f.genFace(t, e, s, d, a, o, p, u, l, r), n++, r = 0, s = [], a = [], o = [], p = [], u = [], l = []);
}), t;
}
// Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
genFace(e, t, n, r, i, s, a, o, p, u) {
for (let l = 2; l < u; l++)
e.vertex.push(t.vertexPositions[n[0]]), e.vertex.push(t.vertexPositions[n[1]]), e.vertex.push(t.vertexPositions[n[2]]), e.vertex.push(t.vertexPositions[n[(l - 1) * 3]]), e.vertex.push(t.vertexPositions[n[(l - 1) * 3 + 1]]), e.vertex.push(t.vertexPositions[n[(l - 1) * 3 + 2]]), e.vertex.push(t.vertexPositions[n[l * 3]]), e.vertex.push(t.vertexPositions[n[l * 3 + 1]]), e.vertex.push(t.vertexPositions[n[l * 3 + 2]]), t.skeleton && (e.vertexWeights.push(o[0]), e.vertexWeights.push(o[1]), e.vertexWeights.push(o[2]), e.vertexWeights.push(o[3]), e.vertexWeights.push(o[(l - 1) * 4]), e.vertexWeights.push(o[(l - 1) * 4 + 1]), e.vertexWeights.push(o[(l - 1) * 4 + 2]), e.vertexWeights.push(o[(l - 1) * 4 + 3]), e.vertexWeights.push(o[l * 4]), e.vertexWeights.push(o[l * 4 + 1]), e.vertexWeights.push(o[l * 4 + 2]), e.vertexWeights.push(o[l * 4 + 3]), e.weightsIndices.push(p[0]), e.weightsIndices.push(p[1]), e.weightsIndices.push(p[2]), e.weightsIndices.push(p[3]), e.weightsIndices.push(p[(l - 1) * 4]), e.weightsIndices.push(p[(l - 1) * 4 + 1]), e.weightsIndices.push(p[(l - 1) * 4 + 2]), e.weightsIndices.push(p[(l - 1) * 4 + 3]), e.weightsIndices.push(p[l * 4]), e.weightsIndices.push(p[l * 4 + 1]), e.weightsIndices.push(p[l * 4 + 2]), e.weightsIndices.push(p[l * 4 + 3])), t.color && (e.colors.push(s[0]), e.colors.push(s[1]), e.colors.push(s[2]), e.colors.push(s[(l - 1) * 3]), e.colors.push(s[(l - 1) * 3 + 1]), e.colors.push(s[(l - 1) * 3 + 2]), e.colors.push(s[l * 3]), e.colors.push(s[l * 3 + 1]), e.colors.push(s[l * 3 + 2])), t.material && t.material.mappingType !== "AllSame" && (e.materialIndex.push(r), e.materialIndex.push(r), e.materialIndex.push(r)), t.normal && (e.normal.push(i[0]), e.normal.push(i[1]), e.normal.push(i[2]), e.normal.push(i[(l - 1) * 3]), e.normal.push(i[(l - 1) * 3 + 1]), e.normal.push(i[(l - 1) * 3 + 2]), e.normal.push(i[l * 3]), e.normal.push(i[l * 3 + 1]), e.normal.push(i[l * 3 + 2])), t.uv && t.uv.forEach(function(f, h) {
e.uvs[h] === void 0 && (e.uvs[h] = []), e.uvs[h].push(a[h][0]), e.uvs[h].push(a[h][1]), e.uvs[h].push(a[h][(l - 1) * 2]), e.uvs[h].push(a[h][(l - 1) * 2 + 1]), e.uvs[h].push(a[h][l * 2]), e.uvs[h].push(a[h][l * 2 + 1]);
});
}
addMorphTargets(e, t, n, r) {
if (n.length === 0)
return;
e.morphTargetsRelative = !0, e.morphAttributes.position = [];
const i = this;
n.forEach(function(s) {
s.rawTargets.forEach(function(a) {
const o = g.Objects.Geometry[a.geoID];
o !== void 0 && i.genMorphGeometry(e, t, o, r, a.name);
});
});
}
// a morph geometry node is similar to a standard node, and the node is also contained
// in FBXTree.Objects.Geometry, however it can only have attributes for position, normal
// and a special attribute Index defining which vertices of the original geometry are affected
// Normal and position attributes only have data for the vertices that are affected by the morph
genMorphGeometry(e, t, n, r, i) {
const s = t.PolygonVertexIndex !== void 0 ? t.PolygonVertexIndex.a : [], a = n.Vertices !== void 0 ? n.Vertices.a : [], o = n.Indexes !== void 0 ? n.Indexes.a : [], p = e.attributes.position.count * 3, u = new Float32Array(p);
for (let m = 0; m < o.length; m++) {
const d = o[m] * 3;
u[d] = a[m * 3], u[d + 1] = a[m * 3 + 1], u[d + 2] = a[m * 3 + 2];
}
const l = {
vertexIndices: s,
vertexPositions: u
}, f = this.genBuffers(l), h = new K(f.vertex, 3);
h.name = i || n.attrName, h.applyMatrix4(r), e.morphAttributes.position.push(h);
}
// Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists
parseNormals(e) {
const t = e.MappingInformationType, n = e.ReferenceInformationType, r = e.Normals.a;
let i = [];
return n === "IndexToDirect" && ("NormalIndex" in e ? i = e.NormalIndex.a : "NormalsIndex" in e && (i = e.NormalsIndex.a)), {
dataSize: 3,
buffer: r,
indices: i,
mappingType: t,
referenceType: n
};
}
// Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists
parseUVs(e) {
const t = e.MappingInformationType, n = e.ReferenceInformationType, r = e.UV.a;
let i = [];
return n === "IndexToDirect" && (i = e.UVIndex.a), {
dataSize: 2,
buffer: r,
indices: i,
mappingType: t,
referenceType: n
};
}
// Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists
parseVertexColors(e) {
const t = e.MappingInformationType, n = e.ReferenceInformationType, r = e.Colors.a;
let i = [];
return n === "IndexToDirect" && (i = e.ColorIndex.a), {
dataSize: 4,
buffer: r,
indices: i,
mappingType: t,
referenceType: n
};
}
// Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists
parseMaterialIndices(e) {
const t = e.MappingInformationType, n = e.ReferenceInformationType;
if (t === "NoMappingInformation")
return {
dataSize: 1,
buffer: [0],
indices: [0],
mappingType: "AllSame",
referenceType: n
};
const r = e.Materials.a, i = [];
for (let s = 0; s < r.length; ++s)
i.push(s);
return {
dataSize: 1,
buffer: r,
indices: i,
mappingType: t,
referenceType: n
};
}
// Generate a NurbGeometry from a node in FBXTree.Objects.Geometry
parseNurbsGeometry(e) {
const t = parseInt(e.Order);
if (isNaN(t))
return console.error("FBXLoader: Invalid Order %s given for geometry ID: %s", e.Order, e.id), new ae();
const n = t - 1, r = e.KnotVector.a, i = [], s = e.Points.a;
for (let l = 0, f = s.length; l < f; l += 4)
i.push(new te().fromArray(s, l));
let a, o;
if (e.Form === "Closed")
i.push(i[0]);
else if (e.Form === "Periodic") {
a = n, o = r.length - 1 - a;
for (let l = 0; l < n; ++l)
i.push(i[l]);
}
const u = new Ut(n, r, i, a, o).getPoints(i.length * 12);
return new ae().setFromPoints(u);
}
}
class zt {
// take raw animation clips and turn them into three.js animation clips
parse() {
const e = [], t = this.parseClips();
if (t !== void 0)
for (const n in t) {
const r = t[n], i = this.addClip(r);
e.push(i);
}
return e;
}
parseClips() {
if (g.Objects.AnimationCurve === void 0)
return;
const e = this.parseAnimationCurveNodes();
this.parseAnimationCurves(e);
const t = this.parseAnimationLayers(e);
return this.parseAnimStacks(t);
}
// parse nodes in FBXTree.Objects.AnimationCurveNode
// each AnimationCurveNode holds data for an animation transform for a model (e.g. left arm rotation )
// and is referenced by an AnimationLayer
parseAnimationCurveNodes() {
const e = g.Objects.AnimationCurveNode, t = /* @__PURE__ */ new Map();
for (const n in e) {
const r = e[n];
if (r.attrName.match(/S|R|T|DeformPercent/) !== null) {
const i = {
id: r.id,
attr: r.attrName,
curves: {}
};
t.set(i.id, i);
}
}
return t;
}
// parse nodes in FBXTree.Objects.AnimationCurve and connect them up to
// previously parsed AnimationCurveNodes. Each AnimationCurve holds data for a single animated
// axis ( e.g. times and values of x rotation)
parseAnimationCurves(e) {
const t = g.Objects.AnimationCurve;
for (const n in t) {
const r = {
id: t[n].id,
times: t[n].KeyTime.a.map($t),
values: t[n].KeyValueFloat.a
}, i = T.get(r.id);
if (i !== void 0) {
const s = i.parents[0].ID, a = i.parents[0].relationship;
a.match(/X/) ? e.get(s).curves.x = r : a.match(/Y/) ? e.get(s).curves.y = r : a.match(/Z/) ? e.get(s).curves.z = r : a.match(/d|DeformPercent/) && e.has(s) && (e.get(s).curves.morph = r);
}
}
}
// parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references
// to various AnimationCurveNodes and is referenced by an AnimationStack node
// note: theoretically a stack can have multiple layers, however in practice there always seems to be one per stack
parseAnimationLayers(e) {
const t = g.Objects.AnimationLayer, n = /* @__PURE__ */ new Map();
for (const r in t) {
const i = [], s = T.get(parseInt(r));
s !== void 0 && (s.children.forEach(function(o, p) {
if (e.has(o.ID)) {
const u = e.get(o.ID);
if (u.curves.x !== void 0 || u.curves.y !== void 0 || u.curves.z !== void 0) {
if (i[p] === void 0) {
const l = T.get(o.ID).parents.filter(function(f) {
return f.relationship !== void 0;
})[0].ID;
if (l !== void 0) {
const f = g.Objects.Model[l.toString()];
if (f === void 0) {
console.warn("FBXLoader: Encountered a unused curve.", o);
return;
}
const h = {
modelName: f.attrName ? ee.sanitizeNodeName(f.attrName) : "",
ID: f.id,
initialPosition: [0, 0, 0],
initialRotation: [0, 0, 0],
initialScale: [1, 1, 1]
};
k.traverse(function(m) {
m.ID === f.id && (h.transform = m.matrix, m.userData.transformData && (h.eulerOrder = m.userData.transformData.eulerOrder));
}), h.transform || (h.transform = new I()), "PreRotation" in f && (h.preRotation = f.PreRotation.value), "PostRotation" in f && (h.postRotation = f.PostRotation.value), i[p] = h;
}
}
i[p] && (i[p][u.attr] = u);
} else if (u.curves.morph !== void 0) {
if (i[p] === void 0) {
const l = T.get(o.ID).parents.filter(function(P) {
return P.relationship !== void 0;
})[0].ID, f = T.get(l).parents[0].ID, h = T.get(f).parents[0].ID, m = T.get(h).parents[0].ID, d = g.Objects.Model[m], v = {
modelName: d.attrName ? ee.sanitizeNodeName(d.attrName) : "",
morphName: g.Objects.Deformer[l].attrName
};
i[p] = v;
}
i[p][u.attr] = u;
}
}
}), n.set(parseInt(r), i));
}
return n;
}
// parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation
// hierarchy. Each Stack node will be used to create a AnimationClip
parseAnimStacks(e) {
const t = g.Objects.AnimationStack, n = {};
for (const r in t) {
const i = T.get(parseInt(r)).children;
i.length > 1 && console.warn("FBXLoader: Encountered an animation stack with multiple layers, this is currently not supported. Ignoring subsequent layers.");
const s = e.get(i[0].ID);
n[r] = {
name: t[r].attrName,
layer: s
};
}
return n;
}
addClip(e) {
let t = [];
const n = this;
return e.layer.forEach(function(r) {
t = t.concat(n.generateTracks(r));
}), new ot(e.name, -1, t);
}
generateTracks(e) {
const t = [];
let n = new U(), r = new N(), i = new U();
if (e.transform && e.transform.decompose(n, r, i), n = n.toArray(), r = new b().setFromQuaternion(r, e.eulerOrder).toArray(), i = i.toArray(), e.T !== void 0 && Object.keys(e.T.curves).length > 0) {
const s = this.generateVectorTrack(e.modelName, e.T.curves, n, "position");
s !== void 0 && t.push(s);
}
if (e.R !== void 0 && Object.keys(e.R.curves).length > 0) {
const s = this.generateRotationTrack(e.modelName, e.R.curves, r, e.preRotation, e.postRotation, e.eulerOrder);
s !== void 0 && t.push(s);
}
if (e.S !== void 0 && Object.keys(e.S.curves).length > 0) {
const s = this.generateVectorTrack(e.modelName, e.S.curves, i, "scale");
s !== void 0 && t.push(s);
}
if (e.DeformPercent !== void 0) {
const s = this.generateMorphTrack(e);
s !== void 0 && t.push(s);
}
return t;
}