Permalink
Cannot retrieve contributors at this time
Fetching contributors…

// namespace | |
var MeshesJS = MeshesJS || {}; | |
;(function() { | |
// Constructor | |
function STLLoader(dropTarget) { | |
this.dropTarget = dropTarget || null; | |
this.addDropListener(); | |
} | |
// methods | |
STLLoader.prototype.onDragLeave = function(e) { | |
e.stopPropagation(); | |
e.preventDefault(); | |
} | |
STLLoader.prototype.onDrop = function(e) { | |
this.onDragLeave(e); | |
this.loadFile((e.target.files || e.dataTransfer.files)[0]); | |
} | |
STLLoader.prototype.addDropListener = function(dropTarget) { | |
var dropTarget = dropTarget || this.dropTarget; | |
if (dropTarget) { | |
var self = this; | |
dropTarget.addEventListener('drop' , function(e) { self.onDrop(e); } , false); | |
dropTarget.addEventListener('dragover' , function(e) { self.onDragLeave(e); }, false); | |
dropTarget.addEventListener('dragleave', function(e) { self.onDragLeave(e); }, false); | |
} | |
}; | |
STLLoader.prototype.removeDropListener = function(dropTarget) { | |
var dropTarget = dropTarget || this.dropTarget; | |
if (dropTarget) { | |
var self = this; | |
dropTarget.removeEventListener('drop' , function(e) { self.onDrop(e); } , false); | |
dropTarget.removeEventListener('dragover' , function(e) { self.onDragLeave(e); }, false); | |
dropTarget.removeEventListener('dragleave', function(e) { self.onDragLeave(e); }, false); | |
} | |
}; | |
STLLoader.prototype.onGeometry = function(geometry) {}; | |
STLLoader.prototype.onError = function(error) {}; | |
STLLoader.prototype.loadFile = function(file) { | |
// self alias | |
var self = this; | |
// file reader instance | |
var reader = new FileReader(); | |
// on file loaded | |
reader.onloadend = function(event) { | |
// if error/abort | |
if (this.error) { | |
self.onError(this.error); | |
return; | |
} | |
// Parse ASCII STL | |
if (typeof this.result === 'string' ) { | |
self.loadString(this.result); | |
return; | |
} | |
// buffer reader | |
var view = new DataView(this.result); | |
// get faces number | |
try { | |
var faces = view.getUint32(80, true); | |
} | |
catch(error) { | |
self.onError(error); | |
return; | |
} | |
// is binary ? | |
var binary = view.byteLength == (80 + 4 + 50 * faces); | |
if (! binary) { | |
// get the file contents as string | |
// (faster than convert array buffer) | |
reader.readAsText(file); | |
return; | |
} | |
// parse binary STL | |
self.loadBinaryData(view, faces); | |
}; | |
// start reading file as array buffer | |
reader.readAsArrayBuffer(file); | |
}; | |
STLLoader.prototype.loadString = function(data) { | |
var length, normal, patternNormal, patternVertex, result, text; | |
var geometry = new THREE.Geometry(); | |
var patternFace = /facet([\s\S]*?)endfacet/g; | |
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; | |
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 = patternNormal.exec(text)) !== null) { | |
normal = new THREE.Vector3( | |
parseFloat(result[1]), | |
parseFloat(result[3]), | |
parseFloat(result[5]) | |
); | |
} | |
while((result = patternVertex.exec(text)) !== null) { | |
geometry.vertices.push(new THREE.Vector3( | |
parseFloat(result[1]), | |
parseFloat(result[3]), | |
parseFloat(result[5]) | |
)); | |
} | |
length = geometry.vertices.length; | |
geometry.faces.push(new THREE.Face3(length-3, length-2, length-1, normal)); | |
} | |
geometry.computeBoundingBox(); | |
geometry.computeBoundingSphere(); | |
this.onGeometry(geometry); | |
}; | |
STLLoader.prototype.loadBinaryData = function(view, faces) { | |
if (! view instanceof DataView) { | |
var view = new DataView(view); | |
} | |
if (! faces) { | |
try { | |
var faces = view.getUint32(80, true); | |
} | |
catch(error) { | |
this.onError(error); | |
return; | |
} | |
} | |
var dataOffset = 84; | |
var faceLength = 12 * 4 + 2; | |
var offset = 0; | |
var geometry = new THREE.BufferGeometry(); | |
var vertices = new Float32Array( faces * 3 * 3 ); | |
var normals = new Float32Array( faces * 3 * 3 ); | |
for ( var face = 0; face < faces; face ++ ) { | |
var start = dataOffset + face * faceLength; | |
var normalX = view.getFloat32( start, true ); | |
var normalY = view.getFloat32( start + 4, true ); | |
var normalZ = view.getFloat32( start + 8, true ); | |
for (var i = 1; i <= 3; i ++) { | |
var vertexstart = start + i * 12; | |
normals[ offset ] = normalX; | |
normals[ offset + 1 ] = normalY; | |
normals[ offset + 2 ] = normalZ; | |
vertices[ offset ] = view.getFloat32( vertexstart, true ); | |
vertices[ offset + 1 ] = view.getFloat32( vertexstart + 4, true ); | |
vertices[ offset + 2 ] = view.getFloat32( vertexstart + 8, true ); | |
offset += 3; | |
} | |
} | |
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3)); | |
geometry.addAttribute('normal', new THREE.BufferAttribute(normals, 3)); | |
this.onGeometry(geometry); | |
}; | |
// export module | |
MeshesJS.STLLoader = STLLoader; | |
})(); |