123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
import { aA as T, i as b, T as j, F as M, o as B, V as w, a6 as V, a3 as L, cX as P, ag as v, cH as E, H as C, cW as D, c0 as A } from "./chunk-IERganv1.js";
import { O as x } from "./chunk-DsOYaBFP.js";
class f {
  constructor() {
    this.materials = [];
  }
  /**
   * This function will read the mtl file and create each material described inside
   * This function could be improve by adding :
   * -some component missing (Ni, Tf...)
   * -including the specific options available
   *
   * @param scene defines the scene the material will be created in
   * @param data defines the mtl data to parse
   * @param rootUrl defines the rooturl to use in order to load relative dependencies
   * @param assetContainer defines the asset container to store the material in (can be null)
   */
  parseMTL(t, n, i, o) {
    if (n instanceof ArrayBuffer)
      return;
    const l = n.split(`
`), h = /\s+/;
    let _, a = null;
    for (let u = 0; u < l.length; u++) {
      const r = l[u].trim();
      if (r.length === 0 || r.charAt(0) === "#")
        continue;
      const s = r.indexOf(" ");
      let e = s >= 0 ? r.substring(0, s) : r;
      e = e.toLowerCase();
      const p = s >= 0 ? r.substring(s + 1).trim() : "";
      if (e === "newmtl")
        a && this.materials.push(a), t._blockEntityCollection = !!o, a = new T(p, t), a._parentContainer = o, t._blockEntityCollection = !1;
      else if (e === "kd" && a)
        _ = p.split(h, 3).map(parseFloat), a.diffuseColor = b.FromArray(_);
      else if (e === "ka" && a)
        _ = p.split(h, 3).map(parseFloat), a.ambientColor = b.FromArray(_);
      else if (e === "ks" && a)
        _ = p.split(h, 3).map(parseFloat), a.specularColor = b.FromArray(_);
      else if (e === "ke" && a)
        _ = p.split(h, 3).map(parseFloat), a.emissiveColor = b.FromArray(_);
      else if (e === "ns" && a)
        a.specularPower = parseFloat(p);
      else if (e === "d" && a)
        a.alpha = parseFloat(p);
      else if (e === "map_ka" && a)
        a.ambientTexture = f._GetTexture(i, p, t);
      else if (e === "map_kd" && a)
        a.diffuseTexture = f._GetTexture(i, p, t);
      else if (e === "map_ks" && a)
        a.specularTexture = f._GetTexture(i, p, t);
      else if (e !== "map_ns") if (e === "map_bump" && a) {
        const d = p.split(h), F = d.indexOf("-bm");
        let g = null;
        F >= 0 && (g = d[F + 1], d.splice(F, 2)), a.bumpTexture = f._GetTexture(i, d.join(" "), t), a.bumpTexture && g !== null && (a.bumpTexture.level = parseFloat(g));
      } else e === "map_d" && a && (a.opacityTexture = f._GetTexture(i, p, t));
    }
    a && this.materials.push(a);
  }
  /**
   * Gets the texture for the material.
   *
   * If the material is imported from input file,
   * We sanitize the url to ensure it takes the texture from aside the material.
   *
   * @param rootUrl The root url to load from
   * @param value The value stored in the mtl
   * @param scene
   * @returns The Texture
   */
  static _GetTexture(t, n, i) {
    if (!n)
      return null;
    let o = t;
    if (t === "file:") {
      let l = n.lastIndexOf("\\");
      l === -1 && (l = n.lastIndexOf("/")), l > -1 ? o += n.substring(l + 1) : o += n;
    } else
      o += n;
    return new j(o, i, !1, f.INVERT_TEXTURE_Y);
  }
}
f.INVERT_TEXTURE_Y = !0;
class m {
  /**
   * Creates a new SolidParser
   * @param materialToUse defines the array to fill with the list of materials to use (it will be filled by the parse function)
   * @param babylonMeshesArray defines the array to fill with the list of loaded meshes (it will be filled by the parse function)
   * @param loadingOptions defines the loading options to use
   */
  constructor(t, n, i) {
    this._positions = [], this._normals = [], this._uvs = [], this._colors = [], this._extColors = [], this._meshesFromObj = [], this._indicesForBabylon = [], this._wrappedPositionForBabylon = [], this._wrappedUvsForBabylon = [], this._wrappedColorsForBabylon = [], this._wrappedNormalsForBabylon = [], this._tuplePosNorm = [], this._curPositionInIndices = 0, this._hasMeshes = !1, this._unwrappedPositionsForBabylon = [], this._unwrappedColorsForBabylon = [], this._unwrappedNormalsForBabylon = [], this._unwrappedUVForBabylon = [], this._triangles = [], this._materialNameFromObj = "", this._objMeshName = "", this._increment = 1, this._isFirstMaterial = !0, this._grayColor = new M(0.5, 0.5, 0.5, 1), this._hasLineData = !1, this._materialToUse = t, this._babylonMeshesArray = n, this._loadingOptions = i;
  }
  /**
   * Search for obj in the given array.
   * This function is called to check if a couple of data already exists in an array.
   *
   * If found, returns the index of the founded tuple index. Returns -1 if not found
   * @param arr Array<{ normals: Array<number>, idx: Array<number> }>
   * @param obj Array<number>
   * @returns {boolean}
   */
  _isInArray(t, n) {
    t[n[0]] || (t[n[0]] = { normals: [], idx: [] });
    const i = t[n[0]].normals.indexOf(n[1]);
    return i === -1 ? -1 : t[n[0]].idx[i];
  }
  _isInArrayUV(t, n) {
    t[n[0]] || (t[n[0]] = { normals: [], idx: [], uv: [] });
    const i = t[n[0]].normals.indexOf(n[1]);
    return i != 1 && n[2] === t[n[0]].uv[i] ? t[n[0]].idx[i] : -1;
  }
  /**
   * This function set the data for each triangle.
   * Data are position, normals and uvs
   * If a tuple of (position, normal) is not set, add the data into the corresponding array
   * If the tuple already exist, add only their indice
   *
   * @param data The vertex's data
   * * indicesPositionFromObj: The index in positions array
   * * indicesUvsFromObj: The index in uvs array
   * * indicesNormalFromObj: The index in normals array
   * * positionVectorFromOBJ: The value of position at index objIndice
   * * textureVectorFromOBJ: The value of uvs
   * * normalsVectorFromOBJ: The value of normals at index objNormale
   * * positionColorsFromOBJ: The value of color at index objIndice
   */
  _setData(t) {
    t.indiceUvsFromObj ?? (t.indiceUvsFromObj = -1), t.indiceNormalFromObj ?? (t.indiceNormalFromObj = -1);
    let n;
    this._loadingOptions.optimizeWithUV ? n = this._isInArrayUV(this._tuplePosNorm, [t.indicePositionFromObj, t.indiceNormalFromObj, t.indiceUvsFromObj]) : n = this._isInArray(this._tuplePosNorm, [t.indicePositionFromObj, t.indiceNormalFromObj]), n === -1 ? (this._indicesForBabylon.push(this._wrappedPositionForBabylon.length), this._wrappedPositionForBabylon.push(t.positionVectorFromOBJ), t.textureVectorFromOBJ !== void 0 && this._wrappedUvsForBabylon.push(t.textureVectorFromOBJ), t.normalsVectorFromOBJ !== void 0 && this._wrappedNormalsForBabylon.push(t.normalsVectorFromOBJ), t.positionColorsFromOBJ !== void 0 && this._wrappedColorsForBabylon.push(t.positionColorsFromOBJ), this._tuplePosNorm[t.indicePositionFromObj].normals.push(t.indiceNormalFromObj), this._tuplePosNorm[t.indicePositionFromObj].idx.push(this._curPositionInIndices++), this._loadingOptions.optimizeWithUV && this._tuplePosNorm[t.indicePositionFromObj].uv.push(t.indiceUvsFromObj)) : this._indicesForBabylon.push(n);
  }
  /**
   * Transform Vector() and BABYLON.Color() objects into numbers in an array
   */
  _unwrapData() {
    try {
      for (let t = 0; t < this._wrappedPositionForBabylon.length; t++)
        this._unwrappedPositionsForBabylon.push(this._wrappedPositionForBabylon[t].x * this._handednessSign, this._wrappedPositionForBabylon[t].y, this._wrappedPositionForBabylon[t].z), this._wrappedNormalsForBabylon.length && this._unwrappedNormalsForBabylon.push(this._wrappedNormalsForBabylon[t].x * this._handednessSign, this._wrappedNormalsForBabylon[t].y, this._wrappedNormalsForBabylon[t].z), this._wrappedUvsForBabylon.length && this._unwrappedUVForBabylon.push(this._wrappedUvsForBabylon[t].x, this._wrappedUvsForBabylon[t].y), this._wrappedColorsForBabylon.length && this._unwrappedColorsForBabylon.push(this._wrappedColorsForBabylon[t].r, this._wrappedColorsForBabylon[t].g, this._wrappedColorsForBabylon[t].b, this._wrappedColorsForBabylon[t].a);
      this._wrappedPositionForBabylon.length = 0, this._wrappedNormalsForBabylon.length = 0, this._wrappedUvsForBabylon.length = 0, this._wrappedColorsForBabylon.length = 0, this._tuplePosNorm.length = 0, this._curPositionInIndices = 0;
    } catch (t) {
      throw new Error("Unable to unwrap data while parsing OBJ data.", { cause: t });
    }
  }
  /**
   * Create triangles from polygons
   * It is important to notice that a triangle is a polygon
   * We get 5 patterns of face defined in OBJ File :
   * facePattern1 = ["1","2","3","4","5","6"]
   * facePattern2 = ["1/1","2/2","3/3","4/4","5/5","6/6"]
   * facePattern3 = ["1/1/1","2/2/2","3/3/3","4/4/4","5/5/5","6/6/6"]
   * facePattern4 = ["1//1","2//2","3//3","4//4","5//5","6//6"]
   * facePattern5 = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-4/-4/-4","-5/-5/-5","-6/-6/-6"]
   * Each pattern is divided by the same method
   * @param faces Array[String] The indices of elements
   * @param v Integer The variable to increment
   */
  _getTriangles(t, n) {
    for (let i = n; i < t.length - 1; i++)
      this._pushTriangle(t, i);
  }
  /**
   * To get color between color and extension color
   * @param index Integer The index of the element in the array
   * @returns value of target color
   */
  _getColor(t) {
    if (this._loadingOptions.importVertexColors)
      return this._extColors[t] ?? this._colors[t];
  }
  /**
   * Create triangles and push the data for each polygon for the pattern 1
   * In this pattern we get vertice positions
   * @param face
   * @param v
   */
  _setDataForCurrentFaceWithPattern1(t, n) {
    this._getTriangles(t, n);
    for (let i = 0; i < this._triangles.length; i++) {
      const o = parseInt(this._triangles[i]) - 1;
      this._setData({
        indicePositionFromObj: o,
        positionVectorFromOBJ: this._positions[o],
        positionColorsFromOBJ: this._getColor(o)
      });
    }
    this._triangles.length = 0;
  }
  /**
   * Create triangles and push the data for each polygon for the pattern 2
   * In this pattern we get vertice positions and uvs
   * @param face
   * @param v
   */
  _setDataForCurrentFaceWithPattern2(t, n) {
    this._getTriangles(t, n);
    for (let i = 0; i < this._triangles.length; i++) {
      const o = this._triangles[i].split("/"), l = parseInt(o[0]) - 1, h = parseInt(o[1]) - 1;
      this._setData({
        indicePositionFromObj: l,
        indiceUvsFromObj: h,
        positionVectorFromOBJ: this._positions[l],
        textureVectorFromOBJ: this._uvs[h],
        positionColorsFromOBJ: this._getColor(l)
      });
    }
    this._triangles.length = 0;
  }
  /**
   * Create triangles and push the data for each polygon for the pattern 3
   * In this pattern we get vertice positions, uvs and normals
   * @param face
   * @param v
   */
  _setDataForCurrentFaceWithPattern3(t, n) {
    this._getTriangles(t, n);
    for (let i = 0; i < this._triangles.length; i++) {
      const o = this._triangles[i].split("/"), l = parseInt(o[0]) - 1, h = parseInt(o[1]) - 1, _ = parseInt(o[2]) - 1;
      this._setData({
        indicePositionFromObj: l,
        indiceUvsFromObj: h,
        indiceNormalFromObj: _,
        positionVectorFromOBJ: this._positions[l],
        textureVectorFromOBJ: this._uvs[h],
        normalsVectorFromOBJ: this._normals[_]
      });
    }
    this._triangles.length = 0;
  }
  /**
   * Create triangles and push the data for each polygon for the pattern 4
   * In this pattern we get vertice positions and normals
   * @param face
   * @param v
   */
  _setDataForCurrentFaceWithPattern4(t, n) {
    this._getTriangles(t, n);
    for (let i = 0; i < this._triangles.length; i++) {
      const o = this._triangles[i].split("//"), l = parseInt(o[0]) - 1, h = parseInt(o[1]) - 1;
      this._setData({
        indicePositionFromObj: l,
        indiceNormalFromObj: h,
        positionVectorFromOBJ: this._positions[l],
        normalsVectorFromOBJ: this._normals[h],
        positionColorsFromOBJ: this._getColor(l)
      });
    }
    this._triangles.length = 0;
  }
  /*
   * Create triangles and push the data for each polygon for the pattern 3
   * In this pattern we get vertice positions, uvs and normals
   * @param face
   * @param v
   */
  _setDataForCurrentFaceWithPattern5(t, n) {
    this._getTriangles(t, n);
    for (let i = 0; i < this._triangles.length; i++) {
      const o = this._triangles[i].split("/"), l = this._positions.length + parseInt(o[0]), h = this._uvs.length + parseInt(o[1]), _ = this._normals.length + parseInt(o[2]);
      this._setData({
        indicePositionFromObj: l,
        indiceUvsFromObj: h,
        indiceNormalFromObj: _,
        positionVectorFromOBJ: this._positions[l],
        textureVectorFromOBJ: this._uvs[h],
        normalsVectorFromOBJ: this._normals[_],
        positionColorsFromOBJ: this._getColor(l)
      });
    }
    this._triangles.length = 0;
  }
  _addPreviousObjMesh() {
    this._meshesFromObj.length > 0 && (this._handledMesh = this._meshesFromObj[this._meshesFromObj.length - 1], this._unwrapData(), this._loadingOptions.useLegacyBehavior && this._indicesForBabylon.reverse(), this._handledMesh.indices = this._indicesForBabylon.slice(), this._handledMesh.positions = this._unwrappedPositionsForBabylon.slice(), this._unwrappedNormalsForBabylon.length && (this._handledMesh.normals = this._unwrappedNormalsForBabylon.slice()), this._unwrappedUVForBabylon.length && (this._handledMesh.uvs = this._unwrappedUVForBabylon.slice()), this._unwrappedColorsForBabylon.length && (this._handledMesh.colors = this._unwrappedColorsForBabylon.slice()), this._handledMesh.hasLines = this._hasLineData, this._indicesForBabylon.length = 0, this._unwrappedPositionsForBabylon.length = 0, this._unwrappedColorsForBabylon.length = 0, this._unwrappedNormalsForBabylon.length = 0, this._unwrappedUVForBabylon.length = 0, this._hasLineData = !1);
  }
  _optimizeNormals(t) {
    const n = t.getVerticesData(B.PositionKind), i = t.getVerticesData(B.NormalKind), o = {};
    if (!n || !i)
      return;
    for (let h = 0; h < n.length / 3; h++) {
      const _ = n[h * 3 + 0], a = n[h * 3 + 1], u = n[h * 3 + 2], r = _ + "_" + a + "_" + u;
      let s = o[r];
      s || (s = [], o[r] = s), s.push(h);
    }
    const l = new w();
    for (const h in o) {
      const _ = o[h];
      if (_.length < 2)
        continue;
      const a = _[0];
      for (let u = 1; u < _.length; ++u) {
        const r = _[u];
        i[a * 3 + 0] += i[r * 3 + 0], i[a * 3 + 1] += i[r * 3 + 1], i[a * 3 + 2] += i[r * 3 + 2];
      }
      l.copyFromFloats(i[a * 3 + 0], i[a * 3 + 1], i[a * 3 + 2]), l.normalize();
      for (let u = 0; u < _.length; ++u) {
        const r = _[u];
        i[r * 3 + 0] = l.x, i[r * 3 + 1] = l.y, i[r * 3 + 2] = l.z;
      }
    }
    t.setVerticesData(B.NormalKind, i);
  }
  static _IsLineElement(t) {
    return t.startsWith("l");
  }
  static _IsObjectElement(t) {
    return t.startsWith("o");
  }
  static _IsGroupElement(t) {
    return t.startsWith("g");
  }
  static _GetZbrushMRGB(t, n) {
    if (!t.startsWith("mrgb"))
      return null;
    if (t = t.replace("mrgb", "").trim(), n)
      return [];
    const i = /[a-z0-9]/g, o = t.match(i);
    if (!o || o.length % 8 !== 0)
      return [];
    const l = [];
    for (let h = 0; h < o.length / 8; h++) {
      const _ = o[h * 8 + 2] + o[h * 8 + 3], a = o[h * 8 + 4] + o[h * 8 + 5], u = o[h * 8 + 6] + o[h * 8 + 7];
      l.push(new M(parseInt(_, 16) / 255, parseInt(a, 16) / 255, parseInt(u, 16) / 255, 1));
    }
    return l;
  }
  /**
   * Function used to parse an OBJ string
   * @param meshesNames defines the list of meshes to load (all if not defined)
   * @param data defines the OBJ string
   * @param scene defines the hosting scene
   * @param assetContainer defines the asset container to load data in
   * @param onFileToLoadFound defines a callback that will be called if a MTL file is found
   */
  parse(t, n, i, o, l) {
    n = n.replace(/#MRGB/g, "mrgb"), n = n.replace(/#.*$/gm, "").trim(), this._loadingOptions.useLegacyBehavior ? (this._pushTriangle = (r, s) => this._triangles.push(r[0], r[s], r[s + 1]), this._handednessSign = 1) : i.useRightHandedSystem ? (this._pushTriangle = (r, s) => this._triangles.push(r[0], r[s + 1], r[s]), this._handednessSign = 1) : (this._pushTriangle = (r, s) => this._triangles.push(r[0], r[s], r[s + 1]), this._handednessSign = -1);
    const h = n.split(`
`), _ = [];
    let a = [];
    _.push(a);
    for (let r = 0; r < h.length; r++) {
      const s = h[r].trim().replace(/\s\s/g, " ");
      if (!(s.length === 0 || s.charAt(0) === "#"))
        if ((m._IsGroupElement(s) || m._IsObjectElement(s)) && (a = [], _.push(a)), m._IsLineElement(s)) {
          const e = s.split(" ");
          for (let p = 1; p < e.length - 1; p++)
            a.push(`l ${e[p]} ${e[p + 1]}`);
        } else
          a.push(s);
    }
    const u = _.flat();
    for (let r = 0; r < u.length; r++) {
      const s = u[r].trim().replace(/\s\s/g, " ");
      let e;
      if (!(s.length === 0 || s.charAt(0) === "#"))
        if (m.VertexPattern.test(s)) {
          if (e = s.match(/[^ ]+/g), this._positions.push(new w(parseFloat(e[1]), parseFloat(e[2]), parseFloat(e[3]))), this._loadingOptions.importVertexColors)
            if (e.length >= 7) {
              const p = parseFloat(e[4]), d = parseFloat(e[5]), F = parseFloat(e[6]);
              this._colors.push(new M(p > 1 ? p / 255 : p, d > 1 ? d / 255 : d, F > 1 ? F / 255 : F, e.length === 7 || e[7] === void 0 ? 1 : parseFloat(e[7])));
            } else
              this._colors.push(this._grayColor);
        } else if ((e = m.NormalPattern.exec(s)) !== null)
          this._normals.push(new w(parseFloat(e[1]), parseFloat(e[2]), parseFloat(e[3])));
        else if ((e = m.UVPattern.exec(s)) !== null)
          this._uvs.push(new V(parseFloat(e[1]) * this._loadingOptions.UVScaling.x, parseFloat(e[2]) * this._loadingOptions.UVScaling.y));
        else if ((e = m.FacePattern3.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern3(
            e[1].trim().split(" "),
            // ["1/1/1", "2/2/2", "3/3/3"]
            1
          );
        else if ((e = m.FacePattern4.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern4(
            e[1].trim().split(" "),
            // ["1//1", "2//2", "3//3"]
            1
          );
        else if ((e = m.FacePattern5.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern5(
            e[1].trim().split(" "),
            // ["-1/-1/-1", "-2/-2/-2", "-3/-3/-3"]
            1
          );
        else if ((e = m.FacePattern2.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern2(
            e[1].trim().split(" "),
            // ["1/1", "2/2", "3/3"]
            1
          );
        else if ((e = m.FacePattern1.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern1(
            e[1].trim().split(" "),
            // ["1", "2", "3"]
            1
          );
        else if ((e = m.LinePattern1.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern1(
            e[1].trim().split(" "),
            // ["1", "2"]
            0
          ), this._hasLineData = !0;
        else if ((e = m.LinePattern2.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern2(
            e[1].trim().split(" "),
            // ["1/1", "2/2"]
            0
          ), this._hasLineData = !0;
        else if (e = m._GetZbrushMRGB(s, !this._loadingOptions.importVertexColors))
          for (const p of e)
            this._extColors.push(p);
        else if ((e = m.LinePattern3.exec(s)) !== null)
          this._setDataForCurrentFaceWithPattern3(
            e[1].trim().split(" "),
            // ["1/1/1", "2/2/2"]
            0
          ), this._hasLineData = !0;
        else if (m.GroupDescriptor.test(s) || m.ObjectDescriptor.test(s)) {
          const p = {
            name: s.substring(2).trim(),
            //Set the name of the current obj mesh
            indices: null,
            positions: null,
            normals: null,
            uvs: null,
            colors: null,
            materialName: this._materialNameFromObj,
            isObject: m.ObjectDescriptor.test(s)
          };
          this._addPreviousObjMesh(), this._meshesFromObj.push(p), this._hasMeshes = !0, this._isFirstMaterial = !0, this._increment = 1;
        } else if (m.UseMtlDescriptor.test(s)) {
          if (this._materialNameFromObj = s.substring(7).trim(), !this._isFirstMaterial || !this._hasMeshes) {
            this._addPreviousObjMesh();
            const p = (
              //Set the name of the current obj mesh
              {
                name: (this._objMeshName || "mesh") + "_mm" + this._increment.toString(),
                //Set the name of the current obj mesh
                indices: null,
                positions: null,
                normals: null,
                uvs: null,
                colors: null,
                materialName: this._materialNameFromObj,
                isObject: !1
              }
            );
            this._increment++, this._meshesFromObj.push(p), this._hasMeshes = !0;
          }
          this._hasMeshes && this._isFirstMaterial && (this._meshesFromObj[this._meshesFromObj.length - 1].materialName = this._materialNameFromObj, this._isFirstMaterial = !1);
        } else m.MtlLibGroupDescriptor.test(s) ? l(s.substring(7).trim()) : m.SmoothDescriptor.test(s) || L.Log("Unhandled expression at line : " + s);
    }
    if (this._hasMeshes && (this._handledMesh = this._meshesFromObj[this._meshesFromObj.length - 1], this._loadingOptions.useLegacyBehavior && this._indicesForBabylon.reverse(), this._unwrapData(), this._handledMesh.indices = this._indicesForBabylon, this._handledMesh.positions = this._unwrappedPositionsForBabylon, this._unwrappedNormalsForBabylon.length && (this._handledMesh.normals = this._unwrappedNormalsForBabylon), this._unwrappedUVForBabylon.length && (this._handledMesh.uvs = this._unwrappedUVForBabylon), this._unwrappedColorsForBabylon.length && (this._handledMesh.colors = this._unwrappedColorsForBabylon), this._handledMesh.hasLines = this._hasLineData), !this._hasMeshes) {
      let r = null;
      if (this._indicesForBabylon.length)
        this._loadingOptions.useLegacyBehavior && this._indicesForBabylon.reverse(), this._unwrapData();
      else {
        for (const s of this._positions)
          this._unwrappedPositionsForBabylon.push(s.x, s.y, s.z);
        if (this._normals.length)
          for (const s of this._normals)
            this._unwrappedNormalsForBabylon.push(s.x, s.y, s.z);
        if (this._uvs.length)
          for (const s of this._uvs)
            this._unwrappedUVForBabylon.push(s.x, s.y);
        if (this._extColors.length)
          for (const s of this._extColors)
            this._unwrappedColorsForBabylon.push(s.r, s.g, s.b, s.a);
        else if (this._colors.length)
          for (const s of this._colors)
            this._unwrappedColorsForBabylon.push(s.r, s.g, s.b, s.a);
        this._materialNameFromObj || (r = new T(P.RandomId(), i), r.pointsCloud = !0, this._materialNameFromObj = r.name, this._normals.length || (r.disableLighting = !0, r.emissiveColor = b.White()));
      }
      this._meshesFromObj.push({
        name: P.RandomId(),
        indices: this._indicesForBabylon,
        positions: this._unwrappedPositionsForBabylon,
        colors: this._unwrappedColorsForBabylon,
        normals: this._unwrappedNormalsForBabylon,
        uvs: this._unwrappedUVForBabylon,
        materialName: this._materialNameFromObj,
        directMaterial: r,
        isObject: !0,
        hasLines: this._hasLineData
      });
    }
    for (let r = 0; r < this._meshesFromObj.length; r++) {
      if (t && this._meshesFromObj[r].name) {
        if (t instanceof Array) {
          if (t.indexOf(this._meshesFromObj[r].name) === -1)
            continue;
        } else if (this._meshesFromObj[r].name !== t)
          continue;
      }
      this._handledMesh = this._meshesFromObj[r], i._blockEntityCollection = !!o;
      const s = new v(this._meshesFromObj[r].name, i);
      if (s._parentContainer = o, i._blockEntityCollection = !1, this._handledMesh._babylonMesh = s, !this._handledMesh.isObject) {
        for (let p = r - 1; p >= 0; --p)
          if (this._meshesFromObj[p].isObject && this._meshesFromObj[p]._babylonMesh) {
            s.parent = this._meshesFromObj[p]._babylonMesh;
            break;
          }
      }
      if (this._materialToUse.push(this._meshesFromObj[r].materialName), this._handledMesh.hasLines && (s._internalMetadata ?? (s._internalMetadata = {}), s._internalMetadata._isLine = !0), this._handledMesh.positions?.length === 0) {
        this._babylonMeshesArray.push(s);
        continue;
      }
      const e = new E();
      if (e.indices = this._handledMesh.indices, e.positions = this._handledMesh.positions, this._loadingOptions.computeNormals || !this._handledMesh.normals) {
        const p = new Array();
        E.ComputeNormals(this._handledMesh.positions, this._handledMesh.indices, p), e.normals = p;
      } else
        e.normals = this._handledMesh.normals;
      this._handledMesh.uvs && (e.uvs = this._handledMesh.uvs), this._handledMesh.colors && (e.colors = this._handledMesh.colors), e.applyToMesh(s), this._loadingOptions.invertY && (s.scaling.y *= -1), this._loadingOptions.optimizeNormals && this._optimizeNormals(s), this._babylonMeshesArray.push(s), this._handledMesh.directMaterial && (s.material = this._handledMesh.directMaterial);
    }
  }
}
m.ObjectDescriptor = /^o/;
m.GroupDescriptor = /^g/;
m.MtlLibGroupDescriptor = /^mtllib /;
m.UseMtlDescriptor = /^usemtl /;
m.SmoothDescriptor = /^s /;
m.VertexPattern = /^v(\s+[\d|.|+|\-|e|E]+){3,7}/;
m.NormalPattern = /^vn(\s+[\d|.|+|\-|e|E]+)( +[\d|.|+|\-|e|E]+)( +[\d|.|+|\-|e|E]+)/;
m.UVPattern = /^vt(\s+[\d|.|+|\-|e|E]+)( +[\d|.|+|\-|e|E]+)/;
m.FacePattern1 = /^f\s+(([\d]{1,}[\s]?){3,})+/;
m.FacePattern2 = /^f\s+((([\d]{1,}\/[\d]{1,}[\s]?){3,})+)/;
m.FacePattern3 = /^f\s+((([\d]{1,}\/[\d]{1,}\/[\d]{1,}[\s]?){3,})+)/;
m.FacePattern4 = /^f\s+((([\d]{1,}\/\/[\d]{1,}[\s]?){3,})+)/;
m.FacePattern5 = /^f\s+(((-[\d]{1,}\/-[\d]{1,}\/-[\d]{1,}[\s]?){3,})+)/;
m.LinePattern1 = /^l\s+(([\d]{1,}[\s]?){2,})+/;
m.LinePattern2 = /^l\s+((([\d]{1,}\/[\d]{1,}[\s]?){2,})+)/;
m.LinePattern3 = /^l\s+((([\d]{1,}\/[\d]{1,}\/[\d]{1,}[\s]?){2,})+)/;
class c {
  /**
   * Invert Y-Axis of referenced textures on load
   */
  static get INVERT_TEXTURE_Y() {
    return f.INVERT_TEXTURE_Y;
  }
  static set INVERT_TEXTURE_Y(t) {
    f.INVERT_TEXTURE_Y = t;
  }
  /**
   * Creates loader for .OBJ files
   *
   * @param loadingOptions options for loading and parsing OBJ/MTL files.
   */
  constructor(t) {
    this.name = x.name, this.extensions = x.extensions, this._assetContainer = null, this._loadingOptions = { ...c._DefaultLoadingOptions, ...t ?? {} };
  }
  static get _DefaultLoadingOptions() {
    return {
      computeNormals: c.COMPUTE_NORMALS,
      optimizeNormals: c.OPTIMIZE_NORMALS,
      importVertexColors: c.IMPORT_VERTEX_COLORS,
      invertY: c.INVERT_Y,
      invertTextureY: c.INVERT_TEXTURE_Y,
      // eslint-disable-next-line @typescript-eslint/naming-convention
      UVScaling: c.UV_SCALING,
      materialLoadingFailsSilently: c.MATERIAL_LOADING_FAILS_SILENTLY,
      optimizeWithUV: c.OPTIMIZE_WITH_UV,
      skipMaterials: c.SKIP_MATERIALS,
      useLegacyBehavior: c.USE_LEGACY_BEHAVIOR
    };
  }
  /**
   * Calls synchronously the MTL file attached to this obj.
   * Load function or importMesh function don't enable to load 2 files in the same time asynchronously.
   * Without this function materials are not displayed in the first frame (but displayed after).
   * In consequence it is impossible to get material information in your HTML file
   *
   * @param url The URL of the MTL file
   * @param rootUrl defines where to load data from
   * @param onSuccess Callback function to be called when the MTL file is loaded
   * @param onFailure
   */
  _loadMTL(t, n, i, o) {
    const l = n + t;
    C.LoadFile(l, i, void 0, void 0, !1, (h, _) => {
      o(l, _);
    });
  }
  /** @internal */
  createPlugin(t) {
    return new c(t[x.name]);
  }
  /**
   * If the data string can be loaded directly.
   * @returns if the data can be loaded directly
   */
  canDirectLoad() {
    return !1;
  }
  /**
   * Imports one or more meshes from the loaded OBJ data and adds them to the scene
   * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
   * @param scene the scene the meshes should be added to
   * @param data the OBJ data to load
   * @param rootUrl root url to load from
   * @returns a promise containing the loaded meshes, particles, skeletons and animations
   */
  // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax
  importMeshAsync(t, n, i, o) {
    return this._parseSolidAsync(t, n, i, o).then((l) => ({
      meshes: l,
      particleSystems: [],
      skeletons: [],
      animationGroups: [],
      transformNodes: [],
      geometries: [],
      lights: [],
      spriteManagers: []
    }));
  }
  /**
   * Imports all objects from the loaded OBJ data and adds them to the scene
   * @param scene the scene the objects should be added to
   * @param data the OBJ data to load
   * @param rootUrl root url to load from
   * @returns a promise which completes when objects have been loaded to the scene
   */
  // eslint-disable-next-line no-restricted-syntax
  loadAsync(t, n, i) {
    return this.importMeshAsync(null, t, n, i).then(() => {
    });
  }
  /**
   * Load into an asset container.
   * @param scene The scene to load into
   * @param data The data to import
   * @param rootUrl The root url for scene and resources
   * @returns The loaded asset container
   */
  // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax
  loadAssetContainerAsync(t, n, i) {
    const o = new D(t);
    return this._assetContainer = o, this.importMeshAsync(null, t, n, i).then((l) => (l.meshes.forEach((h) => o.meshes.push(h)), l.meshes.forEach((h) => {
      const _ = h.material;
      _ && o.materials.indexOf(_) == -1 && (o.materials.push(_), _.getActiveTextures().forEach((u) => {
        o.textures.indexOf(u) == -1 && o.textures.push(u);
      }));
    }), this._assetContainer = null, o)).catch((l) => {
      throw this._assetContainer = null, l;
    });
  }
  /**
   * Read the OBJ file and create an Array of meshes.
   * Each mesh contains all information given by the OBJ and the MTL file.
   * i.e. vertices positions and indices, optional normals values, optional UV values, optional material
   * @param meshesNames defines a string or array of strings of the mesh names that should be loaded from the file
   * @param scene defines the scene where are displayed the data
   * @param data defines the content of the obj file
   * @param rootUrl defines the path to the folder
   * @returns the list of loaded meshes
   */
  // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax
  _parseSolidAsync(t, n, i, o) {
    let l = "";
    const h = new f(), _ = [], a = [];
    i = i.replace(/#.*$/gm, "").trim(), new m(_, a, this._loadingOptions).parse(t, i, n, this._assetContainer, (s) => {
      l = s;
    });
    const r = [];
    return l !== "" && !this._loadingOptions.skipMaterials && r.push(new Promise((s, e) => {
      this._loadMTL(l, o, (p) => {
        try {
          h.parseMTL(n, p, o, this._assetContainer);
          for (let d = 0; d < h.materials.length; d++) {
            let F = 0;
            const g = [];
            let y;
            for (; (y = _.indexOf(h.materials[d].name, F)) > -1; )
              g.push(y), F = y + 1;
            if (y === -1 && g.length === 0)
              h.materials[d].dispose();
            else
              for (let O = 0; O < g.length; O++) {
                const I = a[g[O]], N = h.materials[d];
                I.material = N, I.getTotalIndices() || (N.pointsCloud = !0);
              }
          }
          s();
        } catch (d) {
          C.Warn(`Error processing MTL file: '${l}'`), this._loadingOptions.materialLoadingFailsSilently ? s() : e(d);
        }
      }, (p, d) => {
        C.Warn(`Error downloading MTL file: '${l}'`), this._loadingOptions.materialLoadingFailsSilently ? s() : e(d);
      });
    })), Promise.all(r).then(() => {
      const s = (e) => !!(e._internalMetadata?._isLine ?? !1);
      return a.forEach((e) => {
        if (s(e)) {
          let p = e.material ?? new T(e.name + "_line", n);
          p.getBindedMeshes().filter((F) => !s(F)).length > 0 && (p = p.clone(p.name + "_line") ?? p), p.wireframe = !0, e.material = p, e._internalMetadata && (e._internalMetadata._isLine = void 0);
        }
      }), a;
    });
  }
}
c.OPTIMIZE_WITH_UV = !0;
c.INVERT_Y = !1;
c.IMPORT_VERTEX_COLORS = !1;
c.COMPUTE_NORMALS = !1;
c.OPTIMIZE_NORMALS = !1;
c.UV_SCALING = new V(1, 1);
c.SKIP_MATERIALS = !1;
c.MATERIAL_LOADING_FAILS_SILENTLY = !0;
c.USE_LEGACY_BEHAVIOR = !1;
A(new c());
export {
  c as OBJFileLoader
};