text: import * as THREE from 'three';
  import { DDSLoader } from './DDSLoader'
  
  // https://github.com/mrdoob/three.js/blob/dev/examples/js/loaders/MTLLoader.js
  
  const LoaderHandlers = THREE.Loader.Handlers;
  LoaderHandlers.add( /\.dds$/i, new DDSLoader() );
  
  const MTLLoader = function ( manager ) {
  
      this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
  
  };
  
  MTLLoader.prototype = {
  
      constructor: MTLLoader,
  
      /**
       * 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 setTexturePath
       *
       * @note In order for relative texture references to resolve correctly
       * you must call setPath and/or setTexturePath explicitly prior to load.
       */
      load: function ( url, onLoad, onProgress, onError ) {
  
          var scope = this;
  
          var loader = new THREE.FileLoader( this.manager );
          loader.setPath( this.path );
          loader.load( url, function ( text ) {
  
              onLoad( scope.parse( text ) );
  
          }, onProgress, onError );
  
      },
  
      /**
       * Set base path for resolving references.
       * If set this path will be prepended to each loaded and found reference.
       *
       * @see setTexturePath
       * @param {String} path
       *
       * @example
       *     mtlLoader.setPath( 'assets/obj/' );
       *     mtlLoader.load( 'my.mtl', ... );
       */
      setPath: function ( path ) {
  
          this.path = path;
  
      },
  
      /**
       * Set base path for resolving texture references.
       * If set this path will be prepended found texture reference.
       * If not set and setPath is, it will be used as texture base path.
       *
       * @see setPath
       * @param {String} path
       *
       * @example
       *     mtlLoader.setPath( 'assets/obj/' );
       *     mtlLoader.setTexturePath( 'assets/textures/' );
       *     mtlLoader.load( 'my.mtl', ... );
       */
      setTexturePath: function ( path ) {
  
          this.texturePath = path;
  
      },
  
      setBaseUrl: function ( path ) {
  
          console.warn( 'MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' );
  
          this.setTexturePath( path );
  
      },
  
      setCrossOrigin: function ( value ) {
  
          this.crossOrigin = value;
  
      },
  
      setMaterialOptions: function ( value ) {
  
          this.materialOptions = value;
  
      },
  
      /**
       * Parses a MTL file.
       *
       * @param {String} text - Content of MTL file
       * @return {MTLLoader.MaterialCreator}
       *
       * @see setPath setTexturePath
       *
       * @note In order for relative texture references to resolve correctly
       * you must call setPath and/or setTexturePath explicitly prior to parse.
       */
      parse: function ( text ) {
  
          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 ( info ) {
  
                  if ( key === 'ka' || key === 'kd' || key === 'ks' ) {
  
                      var ss = value.split( delimiter_pattern, 3 );
                      info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
  
                  } else {
  
                      if ( key === 'tr' && value === '1.000000' ) {
                          value = '0.000000';
                          console.log('mtl tr 1.000000 -> 0.000000');
                      }
  
                      info[ key ] = value;
  
                  }
  
              }
  
          }
  
          var materialCreator = new MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions );
          materialCreator.setCrossOrigin( this.crossOrigin );
          materialCreator.setManager( this.manager );
          materialCreator.setMaterials( materialsInfo );
          return materialCreator;
  
      }
  
  };
  
  /**
   * Create a new THREE-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
   *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
   *                  wrap: What type of wrapping to apply for textures
   *                        THREE.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
   */
  
  MTLLoader.MaterialCreator = function ( baseUrl, options ) {
  
      this.baseUrl = baseUrl || '';
      this.options = options;
      this.materialsInfo = {};
      this.materials = {};
      this.materialsArray = [];
      this.nameLookup = {};
  
      this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
      this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;
  
  };
  
  MTLLoader.MaterialCreator.prototype = {
  
      constructor: MTLLoader.MaterialCreator,
  
      crossOrigin: 'Anonymous',
  
      setCrossOrigin: function ( value ) {
  
          this.crossOrigin = value;
  
      },
  
      setManager: function ( value ) {
  
          this.manager = value;
  
      },
  
      setMaterials: function ( materialsInfo ) {
  
          this.materialsInfo = this.convert( materialsInfo );
          this.materials = {};
          this.materialsArray = [];
          this.nameLookup = {};
  
      },
  
      convert: function ( 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;
  
      },
  
      preload: function () {
  
          for ( var mn in this.materialsInfo ) {
  
              this.create( mn );
  
          }
  
      },
  
      getIndex: function ( materialName ) {
  
          return this.nameLookup[ materialName ];
  
      },
  
      getAsArray: function () {
  
          var index = 0;
  
          for ( var mn in this.materialsInfo ) {
  
              this.materialsArray[ index ] = this.create( mn );
              this.nameLookup[ mn ] = index;
              index++;
  
          }
  
          return this.materialsArray;
  
      },
  
      create: function ( materialName ) {
  
          if ( this.materials[ materialName ] === undefined ) {
  
              this.createMaterial_( materialName );
  
          }
  
          return this.materials[ materialName ];
  
      },
  
      createMaterial_: function ( 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;
  
              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 'map_kd':
  
                      // Diffuse texture map
  
                      setMapForType( 'map', value );
  
                      break;
  
                  case 'map_ks':
  
                      // Specular map
  
                      setMapForType( 'specularMap', value );
  
                      break;
  
                  case 'norm':
  
                      setMapForType( 'normalMap', value );
  
                      break;
  
                  case 'map_bump':
                  case 'bump':
  
                      // Bump texture map
  
                      setMapForType( 'bumpMap', value );
  
                      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 ( n > 0 ) {
  
                          params.opacity = 1 - n;
                          params.transparent = true;
  
                      }
  
                      break;
  
                  default:
                      break;
  
              }
  
          }
  
          this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
          return this.materials[ materialName ];
  
      },
  
      getTextureParams: function ( 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;
  
      },
  
      loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
  
          var texture;
          var loader = LoaderHandlers.get( url );
          var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;
  
          if ( loader === null ) {
  
              loader = new THREE.TextureLoader( manager );
  
          }
  
          if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
          texture = loader.load( url, onLoad, onProgress, onError );
  
          if ( mapping !== undefined ) texture.mapping = mapping;
  
          return texture;
  
      }
  
  };
  
  export { MTLLoader };
  