(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "three"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("three"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.three);
    global.MTLLoader = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _three) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.MTLLoader = void 0;

  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }

  function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

  function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

  /**
   * Loads a Wavefront .mtl file specifying materials
   */
  var MTLLoader = /*#__PURE__*/function (_Loader) {
    _inherits(MTLLoader, _Loader);

    var _super = _createSuper(MTLLoader);

    function MTLLoader(manager) {
      _classCallCheck(this, MTLLoader);

      return _super.call(this, manager);
    }
    /**
     * Loads and parses a MTL asset from a URL.
     *
     * @param {String} url - URL to the MTL file.
     * @param {Function} [onLoad] - Callback invoked with the loaded object.
     * @param {Function} [onProgress] - Callback for download progress.
     * @param {Function} [onError] - Callback for download errors.
     *
     * @see setPath setResourcePath
     *
     * @note In order for relative texture references to resolve correctly
     * you must call setResourcePath() explicitly prior to load.
     */


    _createClass(MTLLoader, [{
      key: "load",
      value: function load(url, onLoad, onProgress, onError) {
        var scope = this;
        var path = this.path === '' ? _three.LoaderUtils.extractUrlBase(url) : this.path;
        var loader = new _three.FileLoader(this.manager);
        loader.setPath(this.path);
        loader.setRequestHeader(this.requestHeader);
        loader.setWithCredentials(this.withCredentials);
        loader.load(url, function (text) {
          try {
            onLoad(scope.parse(text, path));
          } catch (e) {
            if (onError) {
              onError(e);
            } else {
              console.error(e);
            }

            scope.manager.itemError(url);
          }
        }, onProgress, onError);
      }
    }, {
      key: "setMaterialOptions",
      value: function setMaterialOptions(value) {
        this.materialOptions = value;
        return this;
      }
      /**
       * Parses a MTL file.
       *
       * @param {String} text - Content of MTL file
       * @return {MaterialCreator}
       *
       * @see setPath setResourcePath
       *
       * @note In order for relative texture references to resolve correctly
       * you must call setResourcePath() explicitly prior to parse.
       */

    }, {
      key: "parse",
      value: function parse(text, path) {
        var lines = text.split('\n');
        var info = {};
        var delimiter_pattern = /\s+/;
        var materialsInfo = {};

        for (var i = 0; i < lines.length; i++) {
          var line = lines[i];
          line = line.trim();

          if (line.length === 0 || line.charAt(0) === '#') {
            // Blank line or comment ignore
            continue;
          }

          var pos = line.indexOf(' ');
          var key = pos >= 0 ? line.substring(0, pos) : line;
          key = key.toLowerCase();
          var value = pos >= 0 ? line.substring(pos + 1) : '';
          value = value.trim();

          if (key === 'newmtl') {
            // New material
            info = {
              name: value
            };
            materialsInfo[value] = info;
          } else {
            if (key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke') {
              var ss = value.split(delimiter_pattern, 3);
              info[key] = [parseFloat(ss[0]), parseFloat(ss[1]), parseFloat(ss[2])];
            } else {
              info[key] = value;
            }
          }
        }

        var materialCreator = new MaterialCreator(this.resourcePath || path, this.materialOptions);
        materialCreator.setCrossOrigin(this.crossOrigin);
        materialCreator.setManager(this.manager);
        materialCreator.setMaterials(materialsInfo);
        return materialCreator;
      }
    }]);

    return MTLLoader;
  }(_three.Loader);
  /**
   * Create a new MTLLoader.MaterialCreator
   * @param baseUrl - Url relative to which textures are loaded
   * @param options - Set of options on how to construct the materials
   *                  side: Which side to apply the material
   *                        FrontSide (default), THREE.BackSide, THREE.DoubleSide
   *                  wrap: What type of wrapping to apply for textures
   *                        RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
   *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
   *                                Default: false, assumed to be already normalized
   *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
   *                                  Default: false
   * @constructor
   */


  _exports.MTLLoader = MTLLoader;

  var MaterialCreator = /*#__PURE__*/function () {
    function MaterialCreator() {
      var baseUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

      _classCallCheck(this, MaterialCreator);

      this.baseUrl = baseUrl;
      this.options = options;
      this.materialsInfo = {};
      this.materials = {};
      this.materialsArray = [];
      this.nameLookup = {};
      this.crossOrigin = 'anonymous';
      this.side = this.options.side !== undefined ? this.options.side : _three.FrontSide;
      this.wrap = this.options.wrap !== undefined ? this.options.wrap : _three.RepeatWrapping;
    }

    _createClass(MaterialCreator, [{
      key: "setCrossOrigin",
      value: function setCrossOrigin(value) {
        this.crossOrigin = value;
        return this;
      }
    }, {
      key: "setManager",
      value: function setManager(value) {
        this.manager = value;
      }
    }, {
      key: "setMaterials",
      value: function setMaterials(materialsInfo) {
        this.materialsInfo = this.convert(materialsInfo);
        this.materials = {};
        this.materialsArray = [];
        this.nameLookup = {};
      }
    }, {
      key: "convert",
      value: function convert(materialsInfo) {
        if (!this.options) return materialsInfo;
        var converted = {};

        for (var mn in materialsInfo) {
          // Convert materials info into normalized form based on options
          var mat = materialsInfo[mn];
          var covmat = {};
          converted[mn] = covmat;

          for (var prop in mat) {
            var save = true;
            var value = mat[prop];
            var lprop = prop.toLowerCase();

            switch (lprop) {
              case 'kd':
              case 'ka':
              case 'ks':
                // Diffuse color (color under white light) using RGB values
                if (this.options && this.options.normalizeRGB) {
                  value = [value[0] / 255, value[1] / 255, value[2] / 255];
                }

                if (this.options && this.options.ignoreZeroRGBs) {
                  if (value[0] === 0 && value[1] === 0 && value[2] === 0) {
                    // ignore
                    save = false;
                  }
                }

                break;

              default:
                break;
            }

            if (save) {
              covmat[lprop] = value;
            }
          }
        }

        return converted;
      }
    }, {
      key: "preload",
      value: function preload() {
        for (var mn in this.materialsInfo) {
          this.create(mn);
        }
      }
    }, {
      key: "getIndex",
      value: function getIndex(materialName) {
        return this.nameLookup[materialName];
      }
    }, {
      key: "getAsArray",
      value: function getAsArray() {
        var index = 0;

        for (var mn in this.materialsInfo) {
          this.materialsArray[index] = this.create(mn);
          this.nameLookup[mn] = index;
          index++;
        }

        return this.materialsArray;
      }
    }, {
      key: "create",
      value: function create(materialName) {
        if (this.materials[materialName] === undefined) {
          this.createMaterial_(materialName);
        }

        return this.materials[materialName];
      }
    }, {
      key: "createMaterial_",
      value: function createMaterial_(materialName) {
        // Create material
        var scope = this;
        var mat = this.materialsInfo[materialName];
        var params = {
          name: materialName,
          side: this.side
        };

        function resolveURL(baseUrl, url) {
          if (typeof url !== 'string' || url === '') return ''; // Absolute URL

          if (/^https?:\/\//i.test(url)) return url;
          return baseUrl + url;
        }

        function setMapForType(mapType, value) {
          if (params[mapType]) return; // Keep the first encountered texture

          var texParams = scope.getTextureParams(value, params);
          var map = scope.loadTexture(resolveURL(scope.baseUrl, texParams.url));
          map.repeat.copy(texParams.scale);
          map.offset.copy(texParams.offset);
          map.wrapS = scope.wrap;
          map.wrapT = scope.wrap;
          params[mapType] = map;
        }

        for (var prop in mat) {
          var value = mat[prop];
          var n = void 0;
          if (value === '') continue;

          switch (prop.toLowerCase()) {
            // Ns is material specular exponent
            case 'kd':
              // Diffuse color (color under white light) using RGB values
              params.color = new _three.Color().fromArray(value);
              break;

            case 'ks':
              // Specular color (color when light is reflected from shiny surface) using RGB values
              params.specular = new _three.Color().fromArray(value);
              break;

            case 'ke':
              // Emissive using RGB values
              params.emissive = new _three.Color().fromArray(value);
              break;

            case 'map_kd':
              // Diffuse texture map
              setMapForType('map', value);
              break;

            case 'map_ks':
              // Specular map
              setMapForType('specularMap', value);
              break;

            case 'map_ke':
              // Emissive map
              setMapForType('emissiveMap', value);
              break;

            case 'norm':
              setMapForType('normalMap', value);
              break;

            case 'map_bump':
            case 'bump':
              // Bump texture map
              setMapForType('bumpMap', value);
              break;

            case 'map_d':
              // Alpha map
              setMapForType('alphaMap', value);
              params.transparent = true;
              break;

            case 'ns':
              // The specular exponent (defines the focus of the specular highlight)
              // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
              params.shininess = parseFloat(value);
              break;

            case 'd':
              n = parseFloat(value);

              if (n < 1) {
                params.opacity = n;
                params.transparent = true;
              }

              break;

            case 'tr':
              n = parseFloat(value);
              if (this.options && this.options.invertTrProperty) n = 1 - n;

              if (n > 0) {
                params.opacity = 1 - n;
                params.transparent = true;
              }

              break;

            default:
              break;
          }
        }

        this.materials[materialName] = new _three.MeshPhongMaterial(params);
        return this.materials[materialName];
      }
    }, {
      key: "getTextureParams",
      value: function getTextureParams(value, matParams) {
        var texParams = {
          scale: new _three.Vector2(1, 1),
          offset: new _three.Vector2(0, 0)
        };
        var items = value.split(/\s+/);
        var pos;
        pos = items.indexOf('-bm');

        if (pos >= 0) {
          matParams.bumpScale = parseFloat(items[pos + 1]);
          items.splice(pos, 2);
        }

        pos = items.indexOf('-s');

        if (pos >= 0) {
          texParams.scale.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
          items.splice(pos, 4); // we expect 3 parameters here!
        }

        pos = items.indexOf('-o');

        if (pos >= 0) {
          texParams.offset.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
          items.splice(pos, 4); // we expect 3 parameters here!
        }

        texParams.url = items.join(' ').trim();
        return texParams;
      }
    }, {
      key: "loadTexture",
      value: function loadTexture(url, mapping, onLoad, onProgress, onError) {
        var manager = this.manager !== undefined ? this.manager : _three.DefaultLoadingManager;
        var loader = manager.getHandler(url);

        if (loader === null) {
          loader = new _three.TextureLoader(manager);
        }

        if (loader.setCrossOrigin) loader.setCrossOrigin(this.crossOrigin);
        var texture = loader.load(url, onLoad, onProgress, onError);
        if (mapping !== undefined) texture.mapping = mapping;
        return texture;
      }
    }]);

    return MaterialCreator;
  }();
});