( function webpackUniversalModuleDefinition ( root , factory ) { if ( typeof exports === 'object' && typeof module === 'object' ) module . exports = factory ( ) ; else if ( typeof define === 'function' && define . amd ) define ( [ ] , factory ) ; else { var a = factory ( ) ; for ( var i in a ) ( typeof exports === 'object' ? exports : root ) [ i ] = a [ i ] ; } } ) ( typeof self !== 'undefined' ? self : this , function ( ) { return /******/ ( function ( modules ) { /******/ /******/ var installedModules = { } ; /******/ /******/ /******/ function __webpack_require__ ( moduleId ) { /******/ /******/ /******/ if ( installedModules [ moduleId ] ) { /******/ return installedModules [ moduleId ] . exports ; } /******/ /******/ var module = ( installedModules [ moduleId ] = { /******/ i : moduleId , /******/ l : false , /******/ exports : { } , } ) ; /******/ /******/ /******/ modules [ moduleId ] . call ( module . exports , module , module . exports , __webpack_require__ ) ; /******/ /******/ /******/ module . l = true ; /******/ /******/ /******/ return module . exports ; } /******/ /******/ /******/ /******/ __webpack_require__ . m = modules ; /******/ /******/ /******/ __webpack_require__ . c = installedModules ; /******/ /******/ /******/ __webpack_require__ . d = function ( exports , name , getter ) { /******/ if ( ! __webpack_require__ . o ( exports , name ) ) { /******/ Object . defineProperty ( exports , name , { enumerable : true , get : getter , } ) ; } } ; /******/ /******/ /******/ __webpack_require__ . r = function ( exports ) { /******/ if ( typeof Symbol !== 'undefined' && Symbol . toStringTag ) { /******/ Object . defineProperty ( exports , Symbol . toStringTag , { value : 'Module' , } ) ; } /******/ Object . defineProperty ( exports , '__esModule' , { value : true , } ) ; } ; /******/ /******/ /******/ /******/ /******/ /******/ /******/ __webpack_require__ . t = function ( value , mode ) { /******/ if ( mode & 1 ) value = __webpack_require__ ( value ) ; /******/ if ( mode & 8 ) return value ; /******/ if ( mode & 4 && typeof value === 'object' && value && value . __esModule ) return value ; /******/ var ns = Object . create ( null ) ; /******/ __webpack_require__ . r ( ns ) ; /******/ Object . defineProperty ( ns , 'default' , { enumerable : true , value : value , } ) ; /******/ if ( mode & 2 && typeof value != 'string' ) for ( var key in value ) __webpack_require__ . d ( ns , key , function ( key ) { return value [ key ] ; } . bind ( null , key ) ) ; /******/ return ns ; } ; /******/ /******/ /******/ __webpack_require__ . n = function ( module ) { /******/ var getter = module && module . __esModule ? /******/ function getDefault ( ) { return module [ 'default' ] ; } : /******/ function getModuleExports ( ) { return module ; } ; /******/ __webpack_require__ . d ( getter , 'a' , getter ) ; /******/ return getter ; } ; /******/ /******/ /******/ __webpack_require__ . o = function ( object , property ) { return Object . prototype . hasOwnProperty . call ( object , property ) ; } ; /******/ /******/ /******/ __webpack_require__ . p = '/' ; /******/ /******/ /******/ /******/ return __webpack_require__ ( ( __webpack_require__ . s = 0 ) ) ; } ) ( { /***/ './src/index.ts' : /***/ function ( module , __webpack_exports__ , __webpack_require__ ) { 'use strict' ; __webpack_require__ . r ( __webpack_exports__ ) ; __webpack_require__ . d ( __webpack_exports__ , 'OBJ' , function ( ) { return OBJ ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'version' , function ( ) { return version ; } ) ; var _mesh__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__ ( './src/mesh.ts' ) ; __webpack_require__ . d ( __webpack_exports__ , 'Mesh' , function ( ) { return _mesh__WEBPACK_IMPORTED_MODULE_0__ [ 'default' ] ; } ) ; var _material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__ ( './src/material.ts' ) ; __webpack_require__ . d ( __webpack_exports__ , 'Material' , function ( ) { return _material__WEBPACK_IMPORTED_MODULE_1__ [ 'Material' ] ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'MaterialLibrary' , function ( ) { return _material__WEBPACK_IMPORTED_MODULE_1__ [ 'MaterialLibrary' ] ; } ) ; var _layout__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__ ( './src/layout.ts' ) ; __webpack_require__ . d ( __webpack_exports__ , 'Attribute' , function ( ) { return _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'Attribute' ] ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'DuplicateAttributeException' , function ( ) { return _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'DuplicateAttributeException' ] ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'Layout' , function ( ) { return _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'Layout' ] ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'TYPES' , function ( ) { return _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'TYPES' ] ; } ) ; var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__ ( './src/utils.ts' ) ; __webpack_require__ . d ( __webpack_exports__ , 'downloadModels' , function ( ) { return _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'downloadModels' ] ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'downloadMeshes' , function ( ) { return _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'downloadMeshes' ] ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'initMeshBuffers' , function ( ) { return _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'initMeshBuffers' ] ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'deleteMeshBuffers' , function ( ) { return _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'deleteMeshBuffers' ] ; } ) ; const version = '2.0.3' ; const OBJ = { Attribute : _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'Attribute' ] , DuplicateAttributeException : _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'DuplicateAttributeException' ] , Layout : _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'Layout' ] , Material : _material__WEBPACK_IMPORTED_MODULE_1__ [ 'Material' ] , MaterialLibrary : _material__WEBPACK_IMPORTED_MODULE_1__ [ 'MaterialLibrary' ] , Mesh : _mesh__WEBPACK_IMPORTED_MODULE_0__ [ 'default' ] , TYPES : _layout__WEBPACK_IMPORTED_MODULE_2__ [ 'TYPES' ] , downloadModels : _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'downloadModels' ] , downloadMeshes : _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'downloadMeshes' ] , initMeshBuffers : _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'initMeshBuffers' ] , deleteMeshBuffers : _utils__WEBPACK_IMPORTED_MODULE_3__ [ 'deleteMeshBuffers' ] , version , } ; } , /***/ './src/layout.ts' : /***/ function ( module , __webpack_exports__ , __webpack_require__ ) { 'use strict' ; __webpack_require__ . r ( __webpack_exports__ ) ; __webpack_require__ . d ( __webpack_exports__ , 'TYPES' , function ( ) { return TYPES ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'DuplicateAttributeException' , function ( ) { return DuplicateAttributeException ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'Attribute' , function ( ) { return Attribute ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'Layout' , function ( ) { return Layout ; } ) ; var TYPES ; ( function ( TYPES ) { TYPES [ 'BYTE' ] = 'BYTE' ; TYPES [ 'UNSIGNED_BYTE' ] = 'UNSIGNED_BYTE' ; TYPES [ 'SHORT' ] = 'SHORT' ; TYPES [ 'UNSIGNED_SHORT' ] = 'UNSIGNED_SHORT' ; TYPES [ 'FLOAT' ] = 'FLOAT' ; } ) ( TYPES || ( TYPES = { } ) ) ; private class DuplicateAttributeException extends Error { param { Attribute } attribute - The attribute that was found more than
                 *        once in the  Layout constructor ( attribute ) { super ( `found duplicate attribute: ${ attribute . key }` ) ; } } private class Attribute { param { string } key param { number } size param { string } type param { boolean } normalized constructor ( key , size , type , normalized = false ) { this . key = key ; this . size = size ; this . type = type ; this . normalized = normalized ; switch ( type ) { case 'BYTE' : case 'UNSIGNED_BYTE' : this . sizeOfType = 1 ; break ; case 'SHORT' : case 'UNSIGNED_SHORT' : this . sizeOfType = 2 ; break ; case 'FLOAT' : this . sizeOfType = 4 ; break ; default : throw new Error ( `Unknown gl type: ${ type }` ) ; } this . sizeInBytes = this . sizeOfType * size ; } } /**
             * A class to represent the memory layout for a vertex attribute array. Used by
             *  Mesh 's TBD(...) method to generate a packed array from mesh data.
             * <p>
             * Layout can sort of be thought of as a C-style struct declaration.
             *  Mesh 's TBD(...) method will use the  Layout instance to
             * pack an array in the given attribute order.
             * <p>
             * Layout also is very helpful when calling a WebGL context's
             * <code>vertexAttribPointer</code> method. If you've created a buffer using
             * a Layout instance, then the same Layout instance can be used to determine
             * the size, type, normalized, stride, and offset parameters for
             * <code>vertexAttribPointer</code>.
             * <p>
             * For example:
             * <pre><code>
             *
             * const index = glctx.getAttribLocation(shaderProgram, "pos");
             * glctx.vertexAttribPointer(
             *   layout.position.size,
             *   glctx[layout.position.type],
             *   layout.position.normalized,
             *   layout.position.stride,
             *   layout.position.offset);
             * </code></pre>
             *  see Mesh class Layout { param { Array } . . attributes see Mesh constructor ( ... attributes ) { this . attributes = attributes ; this . attributeMap = { } ; let offset = 0 ; let maxStrideMultiple = 0 ; for ( const attribute of attributes ) { if ( this . attributeMap [ attribute . key ] ) { throw new DuplicateAttributeException ( attribute ) ; } if ( offset % attribute . sizeOfType !== 0 ) { offset += attribute . sizeOfType - ( offset % attribute . sizeOfType ) ; console . warn ( 'Layout requires padding before ' + attribute . key + ' attribute' ) ; } this . attributeMap [ attribute . key ] = { attribute : attribute , size : attribute . size , type : attribute . type , normalized : attribute . normalized , offset : offset , } ; offset += attribute . sizeInBytes ; maxStrideMultiple = Math . max ( maxStrideMultiple , attribute . sizeOfType ) ; } if ( offset % maxStrideMultiple !== 0 ) { offset += maxStrideMultiple - ( offset % maxStrideMultiple ) ; console . warn ( 'Layout requires padding at the back' ) ; } this . stride = offset ; for ( const attribute of attributes ) { this . attributeMap [ attribute . key ] . stride = this . stride ; } } } see Layout Layout . POSITION = new Attribute ( 'position' , 3 , TYPES . FLOAT ) ; see Layout Layout . NORMAL = new Attribute ( 'normal' , 3 , TYPES . FLOAT ) ; see Layout Layout . TANGENT = new Attribute ( 'tangent' , 3 , TYPES . FLOAT ) ; see Layout Layout . BITANGENT = new Attribute ( 'bitangent' , 3 , TYPES . FLOAT ) ; see Layout Layout . UV = new Attribute ( 'uv' , 2 , TYPES . FLOAT ) ; /**
             * Attribute layout to pack an unsigned short to be interpreted as a the index
             * into a  Mesh 's materials list.
             * <p>
             * The intention of this value is to send all of the  Mesh 's materials
             * into multiple shader uniforms and then reference the current one by this
             * vertex attribute.
             * <p>
             * example glsl code:
             *
             * <pre><code>
             *  // this is bound using MATERIAL_INDEX
             *  attribute int materialIndex;
             *
             *  struct Material {
             *    vec3 diffuse;
             *    vec3 specular;
             *    vec3 specularExponent;
             *  };
             *
             *  uniform Material materials[MAX_MATERIALS];
             *
             *  // ...
             *
             *  vec3 diffuse = materials[materialIndex];
             *
             * </code></pre>
             * TODO: More description & test to make sure subscripting by attributes even
             * works for webgl
             *
             *  see Layout Layout . MATERIAL_INDEX = new Attribute ( 'materialIndex' , 1 , TYPES . SHORT ) ; Layout . MATERIAL_ENABLED = new Attribute ( 'materialEnabled' , 1 , TYPES . UNSIGNED_SHORT ) ; Layout . AMBIENT = new Attribute ( 'ambient' , 3 , TYPES . FLOAT ) ; Layout . DIFFUSE = new Attribute ( 'diffuse' , 3 , TYPES . FLOAT ) ; Layout . SPECULAR = new Attribute ( 'specular' , 3 , TYPES . FLOAT ) ; Layout . SPECULAR_EXPONENT = new Attribute ( 'specularExponent' , 3 , TYPES . FLOAT ) ; Layout . EMISSIVE = new Attribute ( 'emissive' , 3 , TYPES . FLOAT ) ; Layout . TRANSMISSION_FILTER = new Attribute ( 'transmissionFilter' , 3 , TYPES . FLOAT ) ; Layout . DISSOLVE = new Attribute ( 'dissolve' , 1 , TYPES . FLOAT ) ; Layout . ILLUMINATION = new Attribute ( 'illumination' , 1 , TYPES . UNSIGNED_SHORT ) ; Layout . REFRACTION_INDEX = new Attribute ( 'refractionIndex' , 1 , TYPES . FLOAT ) ; Layout . SHARPNESS = new Attribute ( 'sharpness' , 1 , TYPES . FLOAT ) ; Layout . MAP_DIFFUSE = new Attribute ( 'mapDiffuse' , 1 , TYPES . SHORT ) ; Layout . MAP_AMBIENT = new Attribute ( 'mapAmbient' , 1 , TYPES . SHORT ) ; Layout . MAP_SPECULAR = new Attribute ( 'mapSpecular' , 1 , TYPES . SHORT ) ; Layout . MAP_SPECULAR_EXPONENT = new Attribute ( 'mapSpecularExponent' , 1 , TYPES . SHORT ) ; Layout . MAP_DISSOLVE = new Attribute ( 'mapDissolve' , 1 , TYPES . SHORT ) ; Layout . ANTI_ALIASING = new Attribute ( 'antiAliasing' , 1 , TYPES . UNSIGNED_SHORT ) ; Layout . MAP_BUMP = new Attribute ( 'mapBump' , 1 , TYPES . SHORT ) ; Layout . MAP_DISPLACEMENT = new Attribute ( 'mapDisplacement' , 1 , TYPES . SHORT ) ; Layout . MAP_DECAL = new Attribute ( 'mapDecal' , 1 , TYPES . SHORT ) ; Layout . MAP_EMISSIVE = new Attribute ( 'mapEmissive' , 1 , TYPES . SHORT ) ; } , /***/ './src/material.ts' : /***/ function ( module , __webpack_exports__ , __webpack_require__ ) { 'use strict' ; __webpack_require__ . r ( __webpack_exports__ ) ; __webpack_require__ . d ( __webpack_exports__ , 'Material' , function ( ) { return Material ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'MaterialLibrary' , function ( ) { return MaterialLibrary ; } ) ; /**
             * The Material class.
             */ class Material { constructor ( name ) { this . name = name ; param { String } name this . ambient = [ 0 , 0 , 0 ] ; this . diffuse = [ 0 , 0 , 0 ] ; this . specular = [ 0 , 0 , 0 ] ; this . emissive = [ 0 , 0 , 0 ] ; this . transmissionFilter = [ 0 , 0 , 0 ] ; this . dissolve = 0 ; this . specularExponent = 0 ; this . transparency = 0 ; this . illumination = 0 ; this . refractionIndex = 1 ; this . sharpness = 0 ; this . mapDiffuse = emptyTextureOptions ( ) ; this . mapAmbient = emptyTextureOptions ( ) ; this . mapSpecular = emptyTextureOptions ( ) ; this . mapSpecularExponent = emptyTextureOptions ( ) ; this . mapDissolve = emptyTextureOptions ( ) ; this . antiAliasing = false ; this . mapBump = emptyTextureOptions ( ) ; this . mapDisplacement = emptyTextureOptions ( ) ; this . mapDecal = emptyTextureOptions ( ) ; this . mapEmissive = emptyTextureOptions ( ) ; this . mapReflections = [ ] ; } } const SENTINEL_MATERIAL = new Material ( 'sentinel' ) ; /**
             * https://en.wikipedia.org/wiki/Wavefront_.obj_file
             * http://paulbourke.net/dataformats/mtl/
             */ class MaterialLibrary { constructor ( data ) { this . data = data ; param mtlData this . currentMaterial = SENTINEL_MATERIAL ; this . materials = { } ; this . parse ( ) ; } param tokens parse_newmtl ( tokens ) { const name = tokens [ 0 ] ; this . currentMaterial = new Material ( name ) ; this . materials [ name ] = this . currentMaterial ; } param tokens return { * } parseColor ( tokens ) { if ( tokens [ 0 ] == 'spectral' ) { throw new Error ( 'The MTL parser does not support spectral curve files. You will ' + 'need to convert the MTL colors to either RGB or CIEXYZ.' ) ; } if ( tokens [ 0 ] == 'xyz' ) { throw new Error ( 'The MTL parser does not currently support XYZ colors. Either convert the ' + 'XYZ values to RGB or create an issue to add support for XYZ' ) ; } if ( tokens . length == 3 ) { const [ x , y , z ] = tokens ; return [ parseFloat ( x ) , parseFloat ( y ) , parseFloat ( z ) ] ; } const value = parseFloat ( tokens [ 0 ] ) ; return [ value , value , value ] ; } param tokens parse_Ka ( tokens ) { this . currentMaterial . ambient = this . parseColor ( tokens ) ; } param tokens parse_Kd ( tokens ) { this . currentMaterial . diffuse = this . parseColor ( tokens ) ; } param tokens parse_Ks ( tokens ) { this . currentMaterial . specular = this . parseColor ( tokens ) ; } param tokens parse_Ke ( tokens ) { this . currentMaterial . emissive = this . parseColor ( tokens ) ; } param tokens parse_Tf ( tokens ) { this . currentMaterial . transmissionFilter = this . parseColor ( tokens ) ; } param tokens parse_d ( tokens ) { this . currentMaterial . dissolve = parseFloat ( tokens . pop ( ) || '0' ) ; } param tokens parse_illum ( tokens ) { this . currentMaterial . illumination = parseInt ( tokens [ 0 ] ) ; } param tokens parse_Ni ( tokens ) { this . currentMaterial . refractionIndex = parseFloat ( tokens [ 0 ] ) ; } param tokens parse_Ns ( tokens ) { this . currentMaterial . specularExponent = parseInt ( tokens [ 0 ] ) ; } param tokens parse_sharpness ( tokens ) { this . currentMaterial . sharpness = parseInt ( tokens [ 0 ] ) ; } param values param options parse_cc ( values , options ) { options . colorCorrection = values [ 0 ] == 'on' ; } param values param options parse_blendu ( values , options ) { options . horizontalBlending = values [ 0 ] == 'on' ; } param values param options parse_blendv ( values , options ) { options . verticalBlending = values [ 0 ] == 'on' ; } param values param options parse_boost ( values , options ) { options . boostMipMapSharpness = parseFloat ( values [ 0 ] ) ; } param values param options parse_mm ( values , options ) { options . modifyTextureMap . brightness = parseFloat ( values [ 0 ] ) ; options . modifyTextureMap . contrast = parseFloat ( values [ 1 ] ) ; } param values param { Object } option param { Integer } defaultValue parse_ost ( values , option , defaultValue ) { while ( values . length < 3 ) { values . push ( defaultValue . toString ( ) ) ; } option . u = parseFloat ( values [ 0 ] ) ; option . v = parseFloat ( values [ 1 ] ) ; option . w = parseFloat ( values [ 2 ] ) ; } param values param options parse_o ( values , options ) { this . parse_ost ( values , options . offset , 0 ) ; } param values param options parse_s ( values , options ) { this . parse_ost ( values , options . scale , 1 ) ; } param values param options parse_t ( values , options ) { this . parse_ost ( values , options . turbulence , 0 ) ; } param values param options parse_texres ( values , options ) { options . textureResolution = parseFloat ( values [ 0 ] ) ; } param values param options parse_clamp ( values , options ) { options . clamp = values [ 0 ] == 'on' ; } param values param options parse_bm ( values , options ) { options . bumpMultiplier = parseFloat ( values [ 0 ] ) ; } param values param options parse_imfchan ( values , options ) { options . imfChan = values [ 0 ] ; } param values param options parse_type ( values , options ) { options . reflectionType = values [ 0 ] ; } param tokens return { Object } parseOptions ( tokens ) { const options = emptyTextureOptions ( ) ; let option ; let values ; const optionsToValues = { } ; tokens . reverse ( ) ; while ( tokens . length ) { const token = tokens . pop ( ) ; if ( token . startsWith ( '-' ) ) { option = token . substr ( 1 ) ; optionsToValues [ option ] = [ ] ; } else if ( option ) { optionsToValues [ option ] . push ( token ) ; } } for ( option in optionsToValues ) { if ( ! optionsToValues . hasOwnProperty ( option ) ) { continue ; } values = optionsToValues [ option ] ; const optionMethod = this [ `parse_${ option }` ] ; if ( optionMethod ) { optionMethod . bind ( this ) ( values , options ) ; } } return options ; } param tokens return parseMap ( tokens ) { let optionsString ; let filename = '' ; if ( ! tokens [ 0 ] . startsWith ( '-' ) ) { [ filename , ... optionsString ] = tokens ; } else { filename = tokens . pop ( ) ; optionsString = tokens ; } const options = this . parseOptions ( optionsString ) ; options . filename = filename . replace ( /\\/g , '/' ) ; return options ; } param tokens parse_map_Ka ( tokens ) { this . currentMaterial . mapAmbient = this . parseMap ( tokens ) ; } param tokens parse_map_Kd ( tokens ) { this . currentMaterial . mapDiffuse = this . parseMap ( tokens ) ; } param tokens parse_map_Ks ( tokens ) { this . currentMaterial . mapSpecular = this . parseMap ( tokens ) ; } param tokens parse_map_Ke ( tokens ) { this . currentMaterial . mapEmissive = this . parseMap ( tokens ) ; } param tokens parse_map_Ns ( tokens ) { this . currentMaterial . mapSpecularExponent = this . parseMap ( tokens ) ; } param tokens parse_map_d ( tokens ) { this . currentMaterial . mapDissolve = this . parseMap ( tokens ) ; } param tokens parse_map_aat ( tokens ) { this . currentMaterial . antiAliasing = tokens [ 0 ] == 'on' ; } param tokens parse_map_bump ( tokens ) { this . currentMaterial . mapBump = this . parseMap ( tokens ) ; } param tokens parse_bump ( tokens ) { this . parse_map_bump ( tokens ) ; } param tokens parse_disp ( tokens ) { this . currentMaterial . mapDisplacement = this . parseMap ( tokens ) ; } param tokens parse_decal ( tokens ) { this . currentMaterial . mapDecal = this . parseMap ( tokens ) ; } param tokens parse_refl ( tokens ) { this . currentMaterial . mapReflections . push ( this . parseMap ( tokens ) ) ; } /**
                 * Parses the MTL file.
                 *
                 * Iterates line by line parsing each MTL directive.
                 *
                 * This function expects the first token in the line
                 * to be a valid MTL directive. That token is then used
                 * to try and run a method on this class. parse_[directive]
                 * E.g., the `newmtl` directive would try to call the method
                 * parse_newmtl. Each parsing function takes in the remaining
                 * list of tokens and updates the currentMaterial class with
                 * the attributes provided.
                 */ parse ( ) { const lines = this . data . split ( /\r?\n/ ) ; for ( let line of lines ) { line = line . trim ( ) ; if ( ! line || line . startsWith ( '#' ) ) { continue ; } const [ directive , ... tokens ] = line . split ( /\s/ ) ; const parseMethod = this [ `parse_${ directive }` ] ; if ( ! parseMethod ) { console . warn ( `Don't know how to parse the directive: "${ directive }"` ) ; continue ; } parseMethod . bind ( this ) ( tokens ) ; } delete this . data ; this . currentMaterial = SENTINEL_MATERIAL ; } } function emptyTextureOptions ( ) { return { colorCorrection : false , horizontalBlending : true , verticalBlending : true , boostMipMapSharpness : 0 , modifyTextureMap : { brightness : 0 , contrast : 1 , } , offset : { u : 0 , v : 0 , w : 0 } , scale : { u : 1 , v : 1 , w : 1 } , turbulence : { u : 0 , v : 0 , w : 0 } , clamp : false , textureResolution : null , bumpMultiplier : 1 , imfChan : null , filename : '' , } ; } } , /***/ './src/mesh.ts' : /***/ function ( module , __webpack_exports__ , __webpack_require__ ) { 'use strict' ; __webpack_require__ . r ( __webpack_exports__ ) ; __webpack_require__ . d ( __webpack_exports__ , 'default' , function ( ) { return Mesh ; } ) ; var _layout__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__ ( './src/layout.ts' ) ; /**
             * The main Mesh class. The constructor will parse through the OBJ file data
             * and collect the vertex, vertex normal, texture, and face information. This
             * information can then be used later on when creating your VBOs. See
             * OBJ.initMeshBuffers for an example of how to use the newly created Mesh
             */ class Mesh { param { String } objectData param options param { bool } options . enableWTextureCoord param { bool } options . calcTangentsAndBitangents constructor ( objectData , options ) { this . name = '' ; this . indicesPerMaterial = [ ] ; this . materialsByIndex = { } ; this . tangents = [ ] ; this . bitangents = [ ] ; options = options || { } ; options . materials = options . materials || { } ; options . enableWTextureCoord = ! ! options . enableWTextureCoord ; this . vertexNormals = [ ] ; this . textures = [ ] ; this . indices = [ ] ; this . textureStride = options . enableWTextureCoord ? 3 : 2 ; const verts = [ ] ; const vertNormals = [ ] ; const textures = [ ] ; const materialNamesByIndex = [ ] ; const materialIndicesByName = { } ; let currentMaterialIndex = - 1 ; let currentObjectByMaterialIndex = 0 ; const unpacked = { verts : [ ] , norms : [ ] , textures : [ ] , hashindices : { } , indices : [ [ ] ] , materialIndices : [ ] , index : 0 , } ; const VERTEX_RE = /^v\s/ ; const NORMAL_RE = /^vn\s/ ; const TEXTURE_RE = /^vt\s/ ; const FACE_RE = /^f\s/ ; const WHITESPACE_RE = /\s+/ ; const USE_MATERIAL_RE = /^usemtl/ ; const lines = objectData . split ( '\n' ) ; for ( let line of lines ) { line = line . trim ( ) ; if ( ! line || line . startsWith ( '#' ) ) { continue ; } const elements = line . split ( WHITESPACE_RE ) ; elements . shift ( ) ; if ( VERTEX_RE . test ( line ) ) { verts . push ( ... elements ) ; } else if ( NORMAL_RE . test ( line ) ) { vertNormals . push ( ... elements ) ; } else if ( TEXTURE_RE . test ( line ) ) { let coords = elements ; if ( elements . length > 2 && ! options . enableWTextureCoord ) { coords = elements . slice ( 0 , 2 ) ; } else if ( elements . length === 2 && options . enableWTextureCoord ) { coords . push ( '0' ) ; } textures . push ( ... coords ) ; } else if ( USE_MATERIAL_RE . test ( line ) ) { const materialName = elements [ 0 ] ; if ( ! ( materialName in materialIndicesByName ) ) { materialNamesByIndex . push ( materialName ) ; materialIndicesByName [ materialName ] = materialNamesByIndex . length - 1 ; if ( materialIndicesByName [ materialName ] > 0 ) { unpacked . indices . push ( [ ] ) ; } } currentMaterialIndex = materialIndicesByName [ materialName ] ; currentObjectByMaterialIndex = currentMaterialIndex ; } else if ( FACE_RE . test ( line ) ) { const triangles = triangulate ( elements ) ; for ( const triangle of triangles ) { for ( let j = 0 , eleLen = triangle . length ; j < eleLen ; j ++ ) { const hash = triangle [ j ] + ',' + currentMaterialIndex ; if ( hash in unpacked . hashindices ) { unpacked . indices [ currentObjectByMaterialIndex ] . push ( unpacked . hashindices [ hash ] ) ; } else { const vertex = triangle [ j ] . split ( '/' ) ; const normalIndex = vertex . length - 1 ; unpacked . verts . push ( + verts [ ( + vertex [ 0 ] - 1 ) * 3 + 0 ] ) ; unpacked . verts . push ( + verts [ ( + vertex [ 0 ] - 1 ) * 3 + 1 ] ) ; unpacked . verts . push ( + verts [ ( + vertex [ 0 ] - 1 ) * 3 + 2 ] ) ; if ( textures . length ) { const stride = options . enableWTextureCoord ? 3 : 2 ; unpacked . textures . push ( + textures [ ( + vertex [ 1 ] - 1 ) * stride + 0 ] ) ; unpacked . textures . push ( + textures [ ( + vertex [ 1 ] - 1 ) * stride + 1 ] ) ; if ( options . enableWTextureCoord ) { unpacked . textures . push ( + textures [ ( + vertex [ 1 ] - 1 ) * stride + 2 ] ) ; } } unpacked . norms . push ( + vertNormals [ ( + vertex [ normalIndex ] - 1 ) * 3 + 0 ] ) ; unpacked . norms . push ( + vertNormals [ ( + vertex [ normalIndex ] - 1 ) * 3 + 1 ] ) ; unpacked . norms . push ( + vertNormals [ ( + vertex [ normalIndex ] - 1 ) * 3 + 2 ] ) ; unpacked . materialIndices . push ( currentMaterialIndex ) ; unpacked . hashindices [ hash ] = unpacked . index ; unpacked . indices [ currentObjectByMaterialIndex ] . push ( unpacked . hashindices [ hash ] ) ; unpacked . index += 1 ; } } } } } this . vertices = unpacked . verts ; this . vertexNormals = unpacked . norms ; this . textures = unpacked . textures ; this . vertexMaterialIndices = unpacked . materialIndices ; this . indices = unpacked . indices [ currentObjectByMaterialIndex ] ; this . indicesPerMaterial = unpacked . indices ; this . materialNames = materialNamesByIndex ; this . materialIndices = materialIndicesByName ; this . materialsByIndex = { } ; if ( options . calcTangentsAndBitangents ) { this . calculateTangentsAndBitangents ( ) ; } } /**
                 * Calculates the tangents and bitangents of the mesh that forms an orthogonal basis together with the
                 * normal in the direction of the texture coordinates. These are useful for setting up the TBN matrix
                 * when distorting the normals through normal maps.
                 * Method derived from: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-13-normal-mapping/
                 *
                 * This method requires the normals and texture coordinates to be parsed and set up correctly.
                 * Adds the tangents and bitangents as members of the class instance.
                 */ calculateTangentsAndBitangents ( ) { console . assert ( ! ! ( this . vertices && this . vertices . length && this . vertexNormals && this . vertexNormals . length && this . textures && this . textures . length ) , 'Missing attributes for calculating tangents and bitangents' ) ; const unpacked = { tangents : [ ... new Array ( this . vertices . length ) ] . map ( ( _ ) => 0 ) , bitangents : [ ... new Array ( this . vertices . length ) ] . map ( ( _ ) => 0 ) , } ; const indices = this . indices ; const vertices = this . vertices ; const normals = this . vertexNormals ; const uvs = this . textures ; for ( let i = 0 ; i < indices . length ; i += 3 ) { const i0 = indices [ i + 0 ] ; const i1 = indices [ i + 1 ] ; const i2 = indices [ i + 2 ] ; const x_v0 = vertices [ i0 * 3 + 0 ] ; const y_v0 = vertices [ i0 * 3 + 1 ] ; const z_v0 = vertices [ i0 * 3 + 2 ] ; const x_uv0 = uvs [ i0 * 2 + 0 ] ; const y_uv0 = uvs [ i0 * 2 + 1 ] ; const x_v1 = vertices [ i1 * 3 + 0 ] ; const y_v1 = vertices [ i1 * 3 + 1 ] ; const z_v1 = vertices [ i1 * 3 + 2 ] ; const x_uv1 = uvs [ i1 * 2 + 0 ] ; const y_uv1 = uvs [ i1 * 2 + 1 ] ; const x_v2 = vertices [ i2 * 3 + 0 ] ; const y_v2 = vertices [ i2 * 3 + 1 ] ; const z_v2 = vertices [ i2 * 3 + 2 ] ; const x_uv2 = uvs [ i2 * 2 + 0 ] ; const y_uv2 = uvs [ i2 * 2 + 1 ] ; const x_deltaPos1 = x_v1 - x_v0 ; const y_deltaPos1 = y_v1 - y_v0 ; const z_deltaPos1 = z_v1 - z_v0 ; const x_deltaPos2 = x_v2 - x_v0 ; const y_deltaPos2 = y_v2 - y_v0 ; const z_deltaPos2 = z_v2 - z_v0 ; const x_uvDeltaPos1 = x_uv1 - x_uv0 ; const y_uvDeltaPos1 = y_uv1 - y_uv0 ; const x_uvDeltaPos2 = x_uv2 - x_uv0 ; const y_uvDeltaPos2 = y_uv2 - y_uv0 ; const rInv = x_uvDeltaPos1 * y_uvDeltaPos2 - y_uvDeltaPos1 * x_uvDeltaPos2 ; const r = 1.0 / Math . abs ( rInv < 0.0001 ? 1.0 : rInv ) ; const x_tangent = ( x_deltaPos1 * y_uvDeltaPos2 - x_deltaPos2 * y_uvDeltaPos1 ) * r ; const y_tangent = ( y_deltaPos1 * y_uvDeltaPos2 - y_deltaPos2 * y_uvDeltaPos1 ) * r ; const z_tangent = ( z_deltaPos1 * y_uvDeltaPos2 - z_deltaPos2 * y_uvDeltaPos1 ) * r ; const x_bitangent = ( x_deltaPos2 * x_uvDeltaPos1 - x_deltaPos1 * x_uvDeltaPos2 ) * r ; const y_bitangent = ( y_deltaPos2 * x_uvDeltaPos1 - y_deltaPos1 * x_uvDeltaPos2 ) * r ; const z_bitangent = ( z_deltaPos2 * x_uvDeltaPos1 - z_deltaPos1 * x_uvDeltaPos2 ) * r ; const x_n0 = normals [ i0 * 3 + 0 ] ; const y_n0 = normals [ i0 * 3 + 1 ] ; const z_n0 = normals [ i0 * 3 + 2 ] ; const x_n1 = normals [ i1 * 3 + 0 ] ; const y_n1 = normals [ i1 * 3 + 1 ] ; const z_n1 = normals [ i1 * 3 + 2 ] ; const x_n2 = normals [ i2 * 3 + 0 ] ; const y_n2 = normals [ i2 * 3 + 1 ] ; const z_n2 = normals [ i2 * 3 + 2 ] ; const n0_dot_t = x_tangent * x_n0 + y_tangent * y_n0 + z_tangent * z_n0 ; const n1_dot_t = x_tangent * x_n1 + y_tangent * y_n1 + z_tangent * z_n1 ; const n2_dot_t = x_tangent * x_n2 + y_tangent * y_n2 + z_tangent * z_n2 ; const x_resTangent0 = x_tangent - x_n0 * n0_dot_t ; const y_resTangent0 = y_tangent - y_n0 * n0_dot_t ; const z_resTangent0 = z_tangent - z_n0 * n0_dot_t ; const x_resTangent1 = x_tangent - x_n1 * n1_dot_t ; const y_resTangent1 = y_tangent - y_n1 * n1_dot_t ; const z_resTangent1 = z_tangent - z_n1 * n1_dot_t ; const x_resTangent2 = x_tangent - x_n2 * n2_dot_t ; const y_resTangent2 = y_tangent - y_n2 * n2_dot_t ; const z_resTangent2 = z_tangent - z_n2 * n2_dot_t ; const magTangent0 = Math . sqrt ( x_resTangent0 * x_resTangent0 + y_resTangent0 * y_resTangent0 + z_resTangent0 * z_resTangent0 ) ; const magTangent1 = Math . sqrt ( x_resTangent1 * x_resTangent1 + y_resTangent1 * y_resTangent1 + z_resTangent1 * z_resTangent1 ) ; const magTangent2 = Math . sqrt ( x_resTangent2 * x_resTangent2 + y_resTangent2 * y_resTangent2 + z_resTangent2 * z_resTangent2 ) ; const n0_dot_bt = x_bitangent * x_n0 + y_bitangent * y_n0 + z_bitangent * z_n0 ; const n1_dot_bt = x_bitangent * x_n1 + y_bitangent * y_n1 + z_bitangent * z_n1 ; const n2_dot_bt = x_bitangent * x_n2 + y_bitangent * y_n2 + z_bitangent * z_n2 ; const x_resBitangent0 = x_bitangent - x_n0 * n0_dot_bt ; const y_resBitangent0 = y_bitangent - y_n0 * n0_dot_bt ; const z_resBitangent0 = z_bitangent - z_n0 * n0_dot_bt ; const x_resBitangent1 = x_bitangent - x_n1 * n1_dot_bt ; const y_resBitangent1 = y_bitangent - y_n1 * n1_dot_bt ; const z_resBitangent1 = z_bitangent - z_n1 * n1_dot_bt ; const x_resBitangent2 = x_bitangent - x_n2 * n2_dot_bt ; const y_resBitangent2 = y_bitangent - y_n2 * n2_dot_bt ; const z_resBitangent2 = z_bitangent - z_n2 * n2_dot_bt ; const magBitangent0 = Math . sqrt ( x_resBitangent0 * x_resBitangent0 + y_resBitangent0 * y_resBitangent0 + z_resBitangent0 * z_resBitangent0 ) ; const magBitangent1 = Math . sqrt ( x_resBitangent1 * x_resBitangent1 + y_resBitangent1 * y_resBitangent1 + z_resBitangent1 * z_resBitangent1 ) ; const magBitangent2 = Math . sqrt ( x_resBitangent2 * x_resBitangent2 + y_resBitangent2 * y_resBitangent2 + z_resBitangent2 * z_resBitangent2 ) ; unpacked . tangents [ i0 * 3 + 0 ] += x_resTangent0 / magTangent0 ; unpacked . tangents [ i0 * 3 + 1 ] += y_resTangent0 / magTangent0 ; unpacked . tangents [ i0 * 3 + 2 ] += z_resTangent0 / magTangent0 ; unpacked . tangents [ i1 * 3 + 0 ] += x_resTangent1 / magTangent1 ; unpacked . tangents [ i1 * 3 + 1 ] += y_resTangent1 / magTangent1 ; unpacked . tangents [ i1 * 3 + 2 ] += z_resTangent1 / magTangent1 ; unpacked . tangents [ i2 * 3 + 0 ] += x_resTangent2 / magTangent2 ; unpacked . tangents [ i2 * 3 + 1 ] += y_resTangent2 / magTangent2 ; unpacked . tangents [ i2 * 3 + 2 ] += z_resTangent2 / magTangent2 ; unpacked . bitangents [ i0 * 3 + 0 ] += x_resBitangent0 / magBitangent0 ; unpacked . bitangents [ i0 * 3 + 1 ] += y_resBitangent0 / magBitangent0 ; unpacked . bitangents [ i0 * 3 + 2 ] += z_resBitangent0 / magBitangent0 ; unpacked . bitangents [ i1 * 3 + 0 ] += x_resBitangent1 / magBitangent1 ; unpacked . bitangents [ i1 * 3 + 1 ] += y_resBitangent1 / magBitangent1 ; unpacked . bitangents [ i1 * 3 + 2 ] += z_resBitangent1 / magBitangent1 ; unpacked . bitangents [ i2 * 3 + 0 ] += x_resBitangent2 / magBitangent2 ; unpacked . bitangents [ i2 * 3 + 1 ] += y_resBitangent2 / magBitangent2 ; unpacked . bitangents [ i2 * 3 + 2 ] += z_resBitangent2 / magBitangent2 ; } this . tangents = unpacked . tangents ; this . bitangents = unpacked . bitangents ; } param layout - A  Layout object that describes the
                 * desired memory layout of the generated buffer
                 *  return makeBufferData ( layout ) { const numItems = this . vertices . length / 3 ; const buffer = new ArrayBuffer ( layout . stride * numItems ) ; buffer . numItems = numItems ; const dataView = new DataView ( buffer ) ; for ( let i = 0 , vertexOffset = 0 ; i < numItems ; i ++ ) { vertexOffset = i * layout . stride ; for ( const attribute of layout . attributes ) { const offset = vertexOffset + layout . attributeMap [ attribute . key ] . offset ; switch ( attribute . key ) { case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . POSITION . key : dataView . setFloat32 ( offset , this . vertices [ i * 3 ] , true ) ; dataView . setFloat32 ( offset + 4 , this . vertices [ i * 3 + 1 ] , true ) ; dataView . setFloat32 ( offset + 8 , this . vertices [ i * 3 + 2 ] , true ) ; break ; case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . UV . key : dataView . setFloat32 ( offset , this . textures [ i * 2 ] , true ) ; dataView . setFloat32 ( offset + 4 , this . textures [ i * 2 + 1 ] , true ) ; break ; case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . NORMAL . key : dataView . setFloat32 ( offset , this . vertexNormals [ i * 3 ] , true ) ; dataView . setFloat32 ( offset + 4 , this . vertexNormals [ i * 3 + 1 ] , true ) ; dataView . setFloat32 ( offset + 8 , this . vertexNormals [ i * 3 + 2 ] , true ) ; break ; case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . MATERIAL_INDEX . key : dataView . setInt16 ( offset , this . vertexMaterialIndices [ i ] , true ) ; break ; case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . AMBIENT . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . ambient [ 0 ] , true ) ; dataView . setFloat32 ( offset + 4 , material . ambient [ 1 ] , true ) ; dataView . setFloat32 ( offset + 8 , material . ambient [ 2 ] , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . DIFFUSE . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . diffuse [ 0 ] , true ) ; dataView . setFloat32 ( offset + 4 , material . diffuse [ 1 ] , true ) ; dataView . setFloat32 ( offset + 8 , material . diffuse [ 2 ] , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . SPECULAR . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . specular [ 0 ] , true ) ; dataView . setFloat32 ( offset + 4 , material . specular [ 1 ] , true ) ; dataView . setFloat32 ( offset + 8 , material . specular [ 2 ] , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . SPECULAR_EXPONENT . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . specularExponent , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . EMISSIVE . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . emissive [ 0 ] , true ) ; dataView . setFloat32 ( offset + 4 , material . emissive [ 1 ] , true ) ; dataView . setFloat32 ( offset + 8 , material . emissive [ 2 ] , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . TRANSMISSION_FILTER . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . transmissionFilter [ 0 ] , true ) ; dataView . setFloat32 ( offset + 4 , material . transmissionFilter [ 1 ] , true ) ; dataView . setFloat32 ( offset + 8 , material . transmissionFilter [ 2 ] , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . DISSOLVE . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . dissolve , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . ILLUMINATION . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setInt16 ( offset , material . illumination , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . REFRACTION_INDEX . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . refractionIndex , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . SHARPNESS . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setFloat32 ( offset , material . sharpness , true ) ; break ; } case _layout__WEBPACK_IMPORTED_MODULE_0__ [ 'Layout' ] . ANTI_ALIASING . key : { const materialIndex = this . vertexMaterialIndices [ i ] ; const material = this . materialsByIndex [ materialIndex ] ; if ( ! material ) { console . warn ( 'Material "' + this . materialNames [ materialIndex ] + '" not found in mesh. Did you forget to call addMaterialLibrary(...)?"' ) ; break ; } dataView . setInt16 ( offset , material . antiAliasing ? 1 : 0 , true ) ; break ; } } } } return buffer ; } makeIndexBufferData ( ) { const buffer = new Uint16Array ( this . indices ) ; buffer . numItems = this . indices . length ; return buffer ; } makeIndexBufferDataForMaterials ( ... materialIndices ) { const indices = new Array ( ) . concat ( ... materialIndices . map ( ( mtlIdx ) => this . indicesPerMaterial [ mtlIdx ] ) ) ; const buffer = new Uint16Array ( indices ) ; buffer . numItems = indices . length ; return buffer ; } addMaterialLibrary ( mtl ) { for ( const name in mtl . materials ) { if ( ! ( name in this . materialIndices ) ) { continue ; } const material = mtl . materials [ name ] ; const materialIndex = this . materialIndices [ material . name ] ; this . materialsByIndex [ materialIndex ] = material ; } } } function * triangulate ( elements ) { if ( elements . length <= 3 ) { yield elements ; } else if ( elements . length === 4 ) { yield [ elements [ 0 ] , elements [ 1 ] , elements [ 2 ] ] ; yield [ elements [ 2 ] , elements [ 3 ] , elements [ 0 ] ] ; } else { for ( let i = 1 ; i < elements . length - 1 ; i ++ ) { yield [ elements [ 0 ] , elements [ i ] , elements [ i + 1 ] ] ; } } } } , /***/ './src/utils.ts' : /***/ function ( module , __webpack_exports__ , __webpack_require__ ) { 'use strict' ; __webpack_require__ . r ( __webpack_exports__ ) ; __webpack_require__ . d ( __webpack_exports__ , 'downloadModels' , function ( ) { return downloadModels ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'downloadMeshes' , function ( ) { return downloadMeshes ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'initMeshBuffers' , function ( ) { return initMeshBuffers ; } ) ; __webpack_require__ . d ( __webpack_exports__ , 'deleteMeshBuffers' , function ( ) { return deleteMeshBuffers ; } ) ; var _mesh__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__ ( './src/mesh.ts' ) ; var _material__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__ ( './src/material.ts' ) ; function downloadMtlTextures ( mtl , root ) { const mapAttributes = [ 'mapDiffuse' , 'mapAmbient' , 'mapSpecular' , 'mapDissolve' , 'mapBump' , 'mapDisplacement' , 'mapDecal' , 'mapEmissive' ] ; if ( ! root . endsWith ( '/' ) ) { root += '/' ; } const textures = [ ] ; for ( const materialName in mtl . materials ) { if ( ! mtl . materials . hasOwnProperty ( materialName ) ) { continue ; } const material = mtl . materials [ materialName ] ; for ( const attr of mapAttributes ) { const mapData = material [ attr ] ; if ( ! mapData || ! mapData . filename ) { continue ; } const url = root + mapData . filename ; textures . push ( $ . get ( url ) . then ( ( response ) => { if ( ! response . ok ) { throw new Error ( ) ; } return response . blob ( ) ; } ) . then ( function ( data ) { const image = new Image ( ) ; image . src = URL . createObjectURL ( data ) ; mapData . texture = image ; return new Promise ( ( resolve ) => ( image . onload = resolve ) ) ; } ) . catch ( ( ) => { console . debug ( `Unable to download texture: ${ url }` ) ; } ) ) ; } } return Promise . all ( textures ) ; } function getMtl ( modelOptions ) { if ( ! ( typeof modelOptions . mtl === 'string' ) ) { return modelOptions . obj . replace ( /\.obj$/ , '.mtl' ) ; } return modelOptions . mtl ; } returns { Promise } function downloadModels ( models ) { const finished = [ ] ; for ( const model of models ) { if ( ! model . obj ) { throw new Error ( '"obj" attribute of model object not set. The .obj file is required to be set ' + 'in order to use downloadModels()' ) ; } const options = { indicesPerMaterial : ! ! model . indicesPerMaterial , calcTangentsAndBitangents : ! ! model . calcTangentsAndBitangents , } ; let name = model . name ; if ( ! name ) { const parts = model . obj . split ( '/' ) ; name = parts [ parts . length - 1 ] . replace ( '.obj' , '' ) ; } const namePromise = Promise . resolve ( name ) ; const meshPromise = $ . get ( model . obj ) . then ( ( response ) => response ) . then ( ( data ) => { return new _mesh__WEBPACK_IMPORTED_MODULE_0__ [ 'default' ] ( data , options ) ; } ) ; let mtlPromise ; if ( model . mtl ) { const mtl = getMtl ( model ) ; mtlPromise = $ . get ( mtl ) . then ( ( response ) => response ) . then ( ( data ) => { const material = new _material__WEBPACK_IMPORTED_MODULE_1__ [ 'MaterialLibrary' ] ( data ) ; if ( model . downloadMtlTextures !== false ) { let root = model . mtlTextureRoot ; if ( ! root ) { root = mtl . substr ( 0 , mtl . lastIndexOf ( '/' ) ) ; } return Promise . all ( [ Promise . resolve ( material ) , downloadMtlTextures ( material , root ) ] ) ; } return Promise . all ( [ Promise . resolve ( material ) , undefined ] ) ; } ) . then ( ( value ) => { return value [ 0 ] ; } ) ; } const parsed = [ namePromise , meshPromise , mtlPromise ] ; finished . push ( Promise . all ( parsed ) ) ; } return Promise . all ( finished ) . then ( ( ms ) => { const models = { } ; for ( const model of ms ) { const [ name , mesh , mtl ] = model ; mesh . name = name ; if ( mtl ) { mesh . addMaterialLibrary ( mtl ) ; } models [ name ] = mesh ; } return models ; } ) ; } param { Object } nameAndAttrs param { Function } completionCallback param { Object } meshes function downloadMeshes ( nameAndURLs , completionCallback , meshes ) { if ( meshes === undefined ) { meshes = { } ; } const completed = [ ] ; for ( const mesh_name in nameAndURLs ) { if ( ! nameAndURLs . hasOwnProperty ( mesh_name ) ) { continue ; } const url = nameAndURLs [ mesh_name ] ; completed . push ( $ . get ( url ) . then ( ( response ) => response ) . then ( ( data ) => { return [ mesh_name , new _mesh__WEBPACK_IMPORTED_MODULE_0__ [ 'default' ] ( data ) ] ; } ) ) ; } Promise . all ( completed ) . then ( ( ms ) => { for ( const [ name , mesh ] of ms ) { meshes [ name ] = mesh ; } return completionCallback ( meshes ) ; } ) ; } function _buildBuffer ( gl , type , data , itemSize ) { const buffer = gl . createBuffer ( ) ; const arrayView = type === gl . ARRAY_BUFFER ? Float32Array : Uint16Array ; gl . bindBuffer ( type , buffer ) ; gl . bufferData ( type , new arrayView ( data ) , gl . STATIC_DRAW ) ; buffer . itemSize = itemSize ; buffer . numItems = data . length / itemSize ; return buffer ; } param { WebGLRenderingContext } gl param { Mesh } mesh function initMeshBuffers ( gl , mesh ) { mesh . normalBuffer = _buildBuffer ( gl , gl . ARRAY_BUFFER , mesh . vertexNormals , 3 ) ; mesh . textureBuffer = _buildBuffer ( gl , gl . ARRAY_BUFFER , mesh . textures , mesh . textureStride ) ; mesh . vertexBuffer = _buildBuffer ( gl , gl . ARRAY_BUFFER , mesh . vertices , 3 ) ; mesh . indexBuffer = _buildBuffer ( gl , gl . ELEMENT_ARRAY_BUFFER , mesh . indices , 1 ) ; return mesh ; } function deleteMeshBuffers ( gl , mesh ) { gl . deleteBuffer ( mesh . normalBuffer ) ; gl . deleteBuffer ( mesh . textureBuffer ) ; gl . deleteBuffer ( mesh . vertexBuffer ) ; gl . deleteBuffer ( mesh . indexBuffer ) ; } } , /***/ '0' : /***/ function ( module , exports , __webpack_require__ ) { module . exports = __webpack_require__ ( './src/index.ts' ) ; } , } ) ; } ) ;