package/package.json000644 000765 000024 0000001236 13135637033013023 0ustar00000000 000000 { "name": "three-stl-loader", "version": "1.0.6", "description": "@aleeper's three.js stl-loader as a node module", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+https://github.com/enspiral-cherubi/three-stl-loader.git" }, "keywords": [ "three", "threejs", "stl", "loader" ], "author": "data-doge (http://fuckafucka.com)", "license": "MIT", "bugs": { "url": "https://github.com/enspiral-cherubi/three-stl-loader/issues" }, "homepage": "https://github.com/enspiral-cherubi/three-stl-loader#readme" } package/.npmignore000644 000765 000024 0000001021 13116560334012522 0ustar00000000 000000 # Logs logs *.log npm-debug.log* # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory node_modules # Optional npm cache directory .npm # Optional REPL history .node_repl_history package/README.md000644 000765 000024 0000000746 13116560334012017 0ustar00000000 000000 ## three-stl-loader @aleeper's [THREE.STLLoader](http://threejs.org/examples/js/loaders/STLLoader.js) repackaged as a node module ## install `npm i --save three-stl-loader` ## usage ```js var THREE = require('three') var STLLoader = require('three-stl-loader')(THREE) var loader = new STLLoader() loader.load('./path/to/daaaamn.stl', function (geometry) { var material = new THREE.MeshNormalMaterial() var mesh = new THREE.Mesh(geometry, material) scene.add(mesh) }) ``` package/LICENSE000644 000765 000024 0000002071 13116560334011536 0ustar00000000 000000 The MIT License (MIT) Copyright (c) 2016 js-physics-lab Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/index.js000644 000765 000024 0000017176 13135637035012216 0ustar00000000 000000 /** * @author aleeper / http://adamleeper.com/ * @author mrdoob / http://mrdoob.com/ * @author gero3 / https://github.com/gero3 * @author Mugen87 / https://github.com/Mugen87 * * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs. * * Supports both binary and ASCII encoded files, with automatic detection of type. * * The loader returns a non-indexed buffer geometry. * * Limitations: * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL). * There is perhaps some question as to how valid it is to always assume little-endian-ness. * ASCII decoding assumes file is UTF-8. * * Usage: * var loader = new THREE.STLLoader(); * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { * scene.add( new THREE.Mesh( geometry ) ); * }); * * For binary STLs geometry might contain colors for vertices. To use it: * // use the same code to load STL as above * if (geometry.hasColors) { * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors }); * } else { .... } * var mesh = new THREE.Mesh( geometry, material ); */ module.exports = function (THREE) { var STLLoader = function ( manager ) { this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; }; STLLoader.prototype = { constructor: THREE.STLLoader, load: function ( url, onLoad, onProgress, onError ) { var scope = this; var loader = new THREE.FileLoader( scope.manager ); loader.setResponseType( 'arraybuffer' ); loader.load( url, function ( text ) { onLoad( scope.parse( text ) ); }, onProgress, onError ); }, parse: function ( data ) { var isBinary = function () { var expect, face_size, n_faces, reader; reader = new DataView( binData ); face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 ); n_faces = reader.getUint32( 80, true ); expect = 80 + ( 32 / 8 ) + ( n_faces * face_size ); if ( expect === reader.byteLength ) { return true; } // An ASCII STL data must begin with 'solid ' as the first six bytes. // However, ASCII STLs lacking the SPACE after the 'd' are known to be // plentiful. So, check the first 5 bytes for 'solid'. // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' var solid = [ 115, 111, 108, 105, 100 ]; for ( var i = 0; i < 5; i ++ ) { // If solid[ i ] does not match the i-th byte, then it is not an // ASCII STL; hence, it is binary and return true. if ( solid[ i ] != reader.getUint8( i, false ) ) return true; } // First 5 bytes read "solid"; declare it to be an ASCII STL return false; }; var binData = this.ensureBinary( data ); return isBinary() ? this.parseBinary( binData ) : this.parseASCII( this.ensureString( data ) ); }, parseBinary: function ( data ) { var reader = new DataView( data ); var faces = reader.getUint32( 80, true ); var r, g, b, hasColors = false, colors; var defaultR, defaultG, defaultB, alpha; // process STL header // check for default color in header ("COLOR=rgba" sequence). for ( var index = 0; index < 80 - 10; index ++ ) { if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) && ( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) && ( reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) ) { hasColors = true; colors = []; defaultR = reader.getUint8( index + 6 ) / 255; defaultG = reader.getUint8( index + 7 ) / 255; defaultB = reader.getUint8( index + 8 ) / 255; alpha = reader.getUint8( index + 9 ) / 255; } } var dataOffset = 84; var faceLength = 12 * 4 + 2; var geometry = new THREE.BufferGeometry(); var vertices = []; var normals = []; for ( var face = 0; face < faces; face ++ ) { var start = dataOffset + face * faceLength; var normalX = reader.getFloat32( start, true ); var normalY = reader.getFloat32( start + 4, true ); var normalZ = reader.getFloat32( start + 8, true ); if ( hasColors ) { var packedColor = reader.getUint16( start + 48, true ); if ( ( packedColor & 0x8000 ) === 0 ) { // facet has its own unique color r = ( packedColor & 0x1F ) / 31; g = ( ( packedColor >> 5 ) & 0x1F ) / 31; b = ( ( packedColor >> 10 ) & 0x1F ) / 31; } else { r = defaultR; g = defaultG; b = defaultB; } } for ( var i = 1; i <= 3; i ++ ) { var vertexstart = start + i * 12; vertices.push( reader.getFloat32( vertexstart, true ) ); vertices.push( reader.getFloat32( vertexstart + 4, true ) ); vertices.push( reader.getFloat32( vertexstart + 8, true ) ); normals.push( normalX, normalY, normalZ ); if ( hasColors ) { colors.push( r, g, b ); } } } geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) ); geometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) ); if ( hasColors ) { geometry.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( colors ), 3 ) ); geometry.hasColors = true; geometry.alpha = alpha; } return geometry; }, parseASCII: function ( data ) { var geometry, length, patternFace, patternNormal, patternVertex, result, text; geometry = new THREE.BufferGeometry(); patternFace = /facet([\s\S]*?)endfacet/g; var vertices = []; var normals = []; var normal = new THREE.Vector3(); while ( ( result = patternFace.exec( data ) ) !== null ) { text = result[ 0 ]; patternNormal = /normal[\s]+([\-+]?[0-9]+\.?[0-9]*([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+/g; while ( ( result = patternNormal.exec( text ) ) !== null ) { normal.x = parseFloat( result[ 1 ] ); normal.y = parseFloat( result[ 3 ] ); normal.z = parseFloat( result[ 5 ] ); } patternVertex = /vertex[\s]+([\-+]?[0-9]+\.?[0-9]*([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+[\s]+([\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?)+/g; while ( ( result = patternVertex.exec( text ) ) !== null ) { vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 3 ] ), parseFloat( result[ 5 ] ) ); normals.push( normal.x, normal.y, normal.z ); } } geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) ); geometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) ); return geometry; }, ensureString: function ( buf ) { if ( typeof buf !== "string" ) { var array_buffer = new Uint8Array( buf ); var strArray = []; for ( var i = 0; i < buf.byteLength; i ++ ) { strArray.push(String.fromCharCode( array_buffer[ i ] )); // implicitly assumes little-endian } return strArray.join(''); } else { return buf; } }, ensureBinary: function ( buf ) { if ( typeof buf === "string" ) { var array_buffer = new Uint8Array( buf.length ); for ( var i = 0; i < buf.length; i ++ ) { array_buffer[ i ] = buf.charCodeAt( i ) & 0xff; // implicitly assumes little-endian } return array_buffer.buffer || array_buffer; } else { return buf; } } } return STLLoader }