vendor: 21,460 bytes, lines 1-804
1( function () { 2 3 const _object_pattern = /^[og]\s*(.+)?/; // mtllib file_reference 4 5 const _material_library_pattern = /^mtllib /; // usemtl material_name 6 7 const _material_use_pattern = /^usemtl /; // usemap map_name 8 9 const _map_use_pattern = /^usemap /; 10 const _face_vertex_data_separator_pattern = /\s+/; 11 12 const _vA = new THREE.Vector3(); 13 14 const _vB = new THREE.Vector3(); 15 16 const _vC = new THREE.Vector3(); 17 18 const _ab = new THREE.Vector3(); 19 20 const _cb = new THREE.Vector3(); 21 22 const _color = new THREE.Color(); 23 24 function ParserState() { 25 26 const state = { 27 objects: [], 28 object: {}, 29 vertices: [], 30 normals: [], 31 colors: [], 32 uvs: [], 33 materials: {}, 34 materialLibraries: [], 35 startObject: function ( name, fromDeclaration ) { 36 37 // If the current object (initial from reset) is not from a g/o declaration in the parsed 38 // file. We need to use it for the first parsed g/o to keep things in sync. 39 if ( this.object && this.object.fromDeclaration === false ) { 40 41 this.object.name = name; 42 this.object.fromDeclaration = fromDeclaration !== false; 43 return; 44 45 } 46 47 const previousMaterial = this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined; 48 49 if ( this.object && typeof this.object._finalize === 'function' ) { 50 51 this.object._finalize( true ); 52 53 } 54 55 this.object = { 56 name: name || '', 57 fromDeclaration: fromDeclaration !== false, 58 geometry: { 59 vertices: [], 60 normals: [], 61 colors: [], 62 uvs: [], 63 hasUVIndices: false 64 }, 65 materials: [], 66 smooth: true, 67 startMaterial: function ( name, libraries ) { 68 69 const previous = this._finalize( false ); // New usemtl declaration overwrites an inherited material, except if faces were declared 70 // after the material, then it must be preserved for proper MultiMaterial continuation. 71 72 73 if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { 74 75 this.materials.splice( previous.index, 1 ); 76 77 } 78 79 const material = { 80 index: this.materials.length, 81 name: name || '', 82 mtllib: Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '', 83 smooth: previous !== undefined ? previous.smooth : this.smooth, 84 groupStart: previous !== undefined ? previous.groupEnd : 0, 85 groupEnd: - 1, 86 groupCount: - 1, 87 inherited: false, 88 clone: function ( index ) { 89 90 const cloned = { 91 index: typeof index === 'number' ? index : this.index, 92 name: this.name, 93 mtllib: this.mtllib, 94 smooth: this.smooth, 95 groupStart: 0, 96 groupEnd: - 1, 97 groupCount: - 1, 98 inherited: false 99 }; 100 cloned.clone = this.clone.bind( cloned ); 101 return cloned; 102 103 } 104 }; 105 this.materials.push( material ); 106 return material; 107 108 }, 109 currentMaterial: function () { 110 111 if ( this.materials.length > 0 ) { 112 113 return this.materials[ this.materials.length - 1 ]; 114 115 } 116 117 return undefined; 118 119 }, 120 _finalize: function ( end ) { 121 122 const lastMultiMaterial = this.currentMaterial(); 123 124 if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { 125 126 lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; 127 lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; 128 lastMultiMaterial.inherited = false; 129 130 } // Ignore objects tail materials if no face declarations followed them before a new o/g started. 131 132 133 if ( end && this.materials.length > 1 ) { 134 135 for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) { 136 137 if ( this.materials[ mi ].groupCount <= 0 ) { 138 139 this.materials.splice( mi, 1 ); 140 141 } 142 143 } 144 145 } // Guarantee at least one empty material, this makes the creation later more straight forward. 146 147 148 if ( end && this.materials.length === 0 ) { 149 150 this.materials.push( { 151 name: '', 152 smooth: this.smooth 153 } ); 154 155 } 156 157 return lastMultiMaterial; 158 159 } 160 }; // Inherit previous objects material. 161 // Spec tells us that a declared material must be set to all objects until a new material is declared. 162 // If a usemtl declaration is encountered while this new object is being parsed, it will 163 // overwrite the inherited material. Exception being that there was already face declarations 164 // to the inherited material, then it will be preserved for proper MultiMaterial continuation. 165 166 if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { 167 168 const declared = previousMaterial.clone( 0 ); 169 declared.inherited = true; 170 this.object.materials.push( declared ); 171 172 } 173 174 this.objects.push( this.object ); 175 176 }, 177 finalize: function () { 178 179 if ( this.object && typeof this.object._finalize === 'function' ) { 180 181 this.object._finalize( true ); 182 183 } 184 185 }, 186 parseVertexIndex: function ( value, len ) { 187 188 const index = parseInt( value, 10 ); 189 return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; 190 191 }, 192 parseNormalIndex: function ( value, len ) { 193 194 const index = parseInt( value, 10 ); 195 return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; 196 197 }, 198 parseUVIndex: function ( value, len ) { 199 200 const index = parseInt( value, 10 ); 201 return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; 202 203 }, 204 addVertex: function ( a, b, c ) { 205 206 const src = this.vertices; 207 const dst = this.object.geometry.vertices; 208 dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); 209 dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); 210 dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); 211 212 }, 213 addVertexPoint: function ( a ) { 214 215 const src = this.vertices; 216 const dst = this.object.geometry.vertices; 217 dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); 218 219 }, 220 addVertexLine: function ( a ) { 221 222 const src = this.vertices; 223 const dst = this.object.geometry.vertices; 224 dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); 225 226 }, 227 addNormal: function ( a, b, c ) { 228 229 const src = this.normals; 230 const dst = this.object.geometry.normals; 231 dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); 232 dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); 233 dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); 234 235 }, 236 addFaceNormal: function ( a, b, c ) { 237 238 const src = this.vertices; 239 const dst = this.object.geometry.normals; 240 241 _vA.fromArray( src, a ); 242 243 _vB.fromArray( src, b ); 244 245 _vC.fromArray( src, c ); 246 247 _cb.subVectors( _vC, _vB ); 248 249 _ab.subVectors( _vA, _vB ); 250 251 _cb.cross( _ab ); 252 253 _cb.normalize(); 254 255 dst.push( _cb.x, _cb.y, _cb.z ); 256 dst.push( _cb.x, _cb.y, _cb.z ); 257 dst.push( _cb.x, _cb.y, _cb.z ); 258 259 }, 260 addColor: function ( a, b, c ) { 261 262 const src = this.colors; 263 const dst = this.object.geometry.colors; 264 if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); 265 if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); 266 if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); 267 268 }, 269 addUV: function ( a, b, c ) { 270 271 const src = this.uvs; 272 const dst = this.object.geometry.uvs; 273 dst.push( src[ a + 0 ], src[ a + 1 ] ); 274 dst.push( src[ b + 0 ], src[ b + 1 ] ); 275 dst.push( src[ c + 0 ], src[ c + 1 ] ); 276 277 }, 278 addDefaultUV: function () { 279 280 const dst = this.object.geometry.uvs; 281 dst.push( 0, 0 ); 282 dst.push( 0, 0 ); 283 dst.push( 0, 0 ); 284 285 }, 286 addUVLine: function ( a ) { 287 288 const src = this.uvs; 289 const dst = this.object.geometry.uvs; 290 dst.push( src[ a + 0 ], src[ a + 1 ] ); 291 292 }, 293 addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { 294 295 const vLen = this.vertices.length; 296 let ia = this.parseVertexIndex( a, vLen ); 297 let ib = this.parseVertexIndex( b, vLen ); 298 let ic = this.parseVertexIndex( c, vLen ); 299 this.addVertex( ia, ib, ic ); 300 this.addColor( ia, ib, ic ); // normals 301 302 if ( na !== undefined && na !== '' ) { 303 304 const nLen = this.normals.length; 305 ia = this.parseNormalIndex( na, nLen ); 306 ib = this.parseNormalIndex( nb, nLen ); 307 ic = this.parseNormalIndex( nc, nLen ); 308 this.addNormal( ia, ib, ic ); 309 310 } else { 311 312 this.addFaceNormal( ia, ib, ic ); 313 314 } // uvs 315 316 317 if ( ua !== undefined && ua !== '' ) { 318 319 const uvLen = this.uvs.length; 320 ia = this.parseUVIndex( ua, uvLen ); 321 ib = this.parseUVIndex( ub, uvLen ); 322 ic = this.parseUVIndex( uc, uvLen ); 323 this.addUV( ia, ib, ic ); 324 this.object.geometry.hasUVIndices = true; 325 326 } else { 327 328 // add placeholder values (for inconsistent face definitions) 329 this.addDefaultUV(); 330 331 } 332 333 }, 334 addPointGeometry: function ( vertices ) { 335 336 this.object.geometry.type = 'Points'; 337 const vLen = this.vertices.length; 338 339 for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { 340 341 const index = this.parseVertexIndex( vertices[ vi ], vLen ); 342 this.addVertexPoint( index ); 343 this.addColor( index ); 344 345 } 346 347 }, 348 addLineGeometry: function ( vertices, uvs ) { 349 350 this.object.geometry.type = 'Line'; 351 const vLen = this.vertices.length; 352 const uvLen = this.uvs.length; 353 354 for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { 355 356 this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); 357 358 } 359 360 for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { 361 362 this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); 363 364 } 365 366 } 367 }; 368 state.startObject( '', false ); 369 return state; 370 371 } // 372 373 374 class OBJLoader extends THREE.Loader { 375 376 constructor( manager ) { 377 378 super( manager ); 379 this.materials = null; 380 381 } 382 383 load( url, onLoad, onProgress, onError ) { 384 385 const scope = this; 386 const loader = new THREE.FileLoader( this.manager ); 387 loader.setPath( this.path ); 388 loader.setRequestHeader( this.requestHeader ); 389 loader.setWithCredentials( this.withCredentials ); 390 loader.load( url, function ( text ) { 391 392 try { 393 394 onLoad( scope.parse( text ) ); 395 396 } catch ( e ) { 397 398 if ( onError ) { 399 400 onError( e ); 401 402 } else { 403 404 console.error( e ); 405 406 } 407 408 scope.manager.itemError( url ); 409 410 } 411 412 }, onProgress, onError ); 413 414 } 415 416 setMaterials( materials ) { 417 418 this.materials = materials; 419 return this; 420 421 } 422 423 parse( text ) { 424 425 const state = new ParserState(); 426 427 if ( text.indexOf( '\r\n' ) !== - 1 ) { 428 429 // This is faster than String.split with regex that splits on both 430 text = text.replace( /\r\n/g, '\n' ); 431 432 } 433 434 if ( text.indexOf( '\\\n' ) !== - 1 ) { 435 436 // join lines separated by a line continuation character (\) 437 text = text.replace( /\\\n/g, '' ); 438 439 } 440 441 const lines = text.split( '\n' ); 442 let result = []; 443 444 for ( let i = 0, l = lines.length; i < l; i ++ ) { 445 446 const line = lines[ i ].trimStart(); 447 if ( line.length === 0 ) continue; 448 const lineFirstChar = line.charAt( 0 ); // @todo invoke passed in handler if any 449 450 if ( lineFirstChar === '#' ) continue; 451 452 if ( lineFirstChar === 'v' ) { 453 454 const data = line.split( _face_vertex_data_separator_pattern ); 455 456 switch ( data[ 0 ] ) { 457 458 case 'v': 459 state.vertices.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) ); 460 461 if ( data.length >= 7 ) { 462 463 _color.setRGB( parseFloat( data[ 4 ] ), parseFloat( data[ 5 ] ), parseFloat( data[ 6 ] ) ).convertSRGBToLinear(); 464 465 state.colors.push( _color.r, _color.g, _color.b ); 466 467 } else { 468 469 // if no colors are defined, add placeholders so color and vertex indices match 470 state.colors.push( undefined, undefined, undefined ); 471 472 } 473 474 break; 475 476 case 'vn': 477 state.normals.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) ); 478 break; 479 480 case 'vt': 481 state.uvs.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) ); 482 break; 483 484 } 485 486 } else if ( lineFirstChar === 'f' ) { 487 488 const lineData = line.slice( 1 ).trim(); 489 const vertexData = lineData.split( _face_vertex_data_separator_pattern ); 490 const faceVertices = []; // Parse the face vertex data into an easy to work with format 491 492 for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) { 493 494 const vertex = vertexData[ j ]; 495 496 if ( vertex.length > 0 ) { 497 498 const vertexParts = vertex.split( '/' ); 499 faceVertices.push( vertexParts ); 500 501 } 502 503 } // Draw an edge between the first vertex and all subsequent vertices to form an n-gon 504 505 506 const v1 = faceVertices[ 0 ]; 507 508 for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { 509 510 const v2 = faceVertices[ j ]; 511 const v3 = faceVertices[ j + 1 ]; 512 state.addFace( v1[ 0 ], v2[ 0 ], v3[ 0 ], v1[ 1 ], v2[ 1 ], v3[ 1 ], v1[ 2 ], v2[ 2 ], v3[ 2 ] ); 513 514 } 515 516 } else if ( lineFirstChar === 'l' ) { 517 518 const lineParts = line.substring( 1 ).trim().split( ' ' ); 519 let lineVertices = []; 520 const lineUVs = []; 521 522 if ( line.indexOf( '/' ) === - 1 ) { 523 524 lineVertices = lineParts; 525 526 } else { 527 528 for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) { 529 530 const parts = lineParts[ li ].split( '/' ); 531 if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] ); 532 if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] ); 533 534 } 535 536 } 537 538 state.addLineGeometry( lineVertices, lineUVs ); 539 540 } else if ( lineFirstChar === 'p' ) { 541 542 const lineData = line.slice( 1 ).trim(); 543 const pointData = lineData.split( ' ' ); 544 state.addPointGeometry( pointData ); 545 546 } else if ( ( result = _object_pattern.exec( line ) ) !== null ) { 547 548 // o object_name 549 // or 550 // g group_name 551 // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 552 // let name = result[ 0 ].slice( 1 ).trim(); 553 const name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 ); 554 state.startObject( name ); 555 556 } else if ( _material_use_pattern.test( line ) ) { 557 558 // material 559 state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); 560 561 } else if ( _material_library_pattern.test( line ) ) { 562 563 // mtl file 564 state.materialLibraries.push( line.substring( 7 ).trim() ); 565 566 } else if ( _map_use_pattern.test( line ) ) { 567 568 // the line is parsed but ignored since the loader assumes textures are defined MTL files 569 // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method) 570 console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' ); 571 572 } else if ( lineFirstChar === 's' ) { 573 574 result = line.split( ' ' ); // smooth shading 575 // @todo Handle files that have varying smooth values for a set of faces inside one geometry, 576 // but does not define a usemtl for each face set. 577 // This should be detected and a dummy material created (later MultiMaterial and geometry groups). 578 // This requires some care to not create extra material on each smooth value for "normal" obj files. 579 // where explicit usemtl defines geometry groups. 580 // Example asset: examples/models/obj/cerberus/Cerberus.obj 581 582 /* 583 * http://paulbourke.net/dataformats/obj/ 584 * 585 * From chapter "Grouping" Syntax explanation "s group_number": 586 * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. 587 * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form 588 * surfaces, smoothing groups are either turned on or off; there is no difference between values greater 589 * than 0." 590 */ 591 592 if ( result.length > 1 ) { 593 594 const value = result[ 1 ].trim().toLowerCase(); 595 state.object.smooth = value !== '0' && value !== 'off'; 596 597 } else { 598 599 // ZBrush can produce "s" lines #11707 600 state.object.smooth = true; 601 602 } 603 604 const material = state.object.currentMaterial(); 605 if ( material ) material.smooth = state.object.smooth; 606 607 } else { 608 609 // Handle null terminated files without exception 610 if ( line === '\0' ) continue; 611 console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); 612 613 } 614 615 } 616 617 state.finalize(); 618 const container = new THREE.Group(); 619 container.materialLibraries = [].concat( state.materialLibraries ); 620 const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 ); 621 622 if ( hasPrimitives === true ) { 623 624 for ( let i = 0, l = state.objects.length; i < l; i ++ ) { 625 626 const object = state.objects[ i ]; 627 const geometry = object.geometry; 628 const materials = object.materials; 629 const isLine = geometry.type === 'Line'; 630 const isPoints = geometry.type === 'Points'; 631 let hasVertexColors = false; // Skip o/g line declarations that did not follow with any faces 632 633 if ( geometry.vertices.length === 0 ) continue; 634 const buffergeometry = new THREE.BufferGeometry(); 635 buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); 636 637 if ( geometry.normals.length > 0 ) { 638 639 buffergeometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); 640 641 } 642 643 if ( geometry.colors.length > 0 ) { 644 645 hasVertexColors = true; 646 buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); 647 648 } 649 650 if ( geometry.hasUVIndices === true ) { 651 652 buffergeometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); 653 654 } // Create materials 655 656 657 const createdMaterials = []; 658 659 for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { 660 661 const sourceMaterial = materials[ mi ]; 662 const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors; 663 let material = state.materials[ materialHash ]; 664 665 if ( this.materials !== null ) { 666 667 material = this.materials.create( sourceMaterial.name ); // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. 668 669 if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { 670 671 const materialLine = new THREE.LineBasicMaterial(); 672 THREE.Material.prototype.copy.call( materialLine, material ); 673 materialLine.color.copy( material.color ); 674 material = materialLine; 675 676 } else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { 677 678 const materialPoints = new THREE.PointsMaterial( { 679 size: 10, 680 sizeAttenuation: false 681 } ); 682 THREE.Material.prototype.copy.call( materialPoints, material ); 683 materialPoints.color.copy( material.color ); 684 materialPoints.map = material.map; 685 material = materialPoints; 686 687 } 688 689 } 690 691 if ( material === undefined ) { 692 693 if ( isLine ) { 694 695 material = new THREE.LineBasicMaterial(); 696 697 } else if ( isPoints ) { 698 699 material = new THREE.PointsMaterial( { 700 size: 1, 701 sizeAttenuation: false 702 } ); 703 704 } else { 705 706 material = new THREE.MeshPhongMaterial(); 707 708 } 709 710 material.name = sourceMaterial.name; 711 material.flatShading = sourceMaterial.smooth ? false : true; 712 material.vertexColors = hasVertexColors; 713 state.materials[ materialHash ] = material; 714 715 } 716 717 createdMaterials.push( material ); 718 719 } // Create mesh 720 721 722 let mesh; 723 724 if ( createdMaterials.length > 1 ) { 725 726 for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { 727 728 const sourceMaterial = materials[ mi ]; 729 buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); 730 731 } 732 733 if ( isLine ) { 734 735 mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); 736 737 } else if ( isPoints ) { 738 739 mesh = new THREE.Points( buffergeometry, createdMaterials ); 740 741 } else { 742 743 mesh = new THREE.Mesh( buffergeometry, createdMaterials ); 744 745 } 746 747 } else { 748 749 if ( isLine ) { 750 751 mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); 752 753 } else if ( isPoints ) { 754 755 mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); 756 757 } else { 758 759 mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); 760 761 } 762 763 } 764 765 mesh.name = object.name; 766 container.add( mesh ); 767 768 } 769 770 } else { 771 772 // if there is only the default parser state object with no geometry data, interpret data as point cloud 773 if ( state.vertices.length > 0 ) { 774 775 const material = new THREE.PointsMaterial( { 776 size: 1, 777 sizeAttenuation: false 778 } ); 779 const buffergeometry = new THREE.BufferGeometry(); 780 buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( state.vertices, 3 ) ); 781 782 if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) { 783 784 buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( state.colors, 3 ) ); 785 material.vertexColors = true; 786 787 } 788 789 const points = new THREE.Points( buffergeometry, material ); 790 container.add( points ); 791 792 } 793 794 } 795 796 return container; 797 798 } 799 800 } 801 802 THREE.OBJLoader = OBJLoader; 803 804} )();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.