Skip to content

Instantly share code, notes, and snippets.

@filharvey
Last active February 4, 2017 23:12
Show Gist options
  • Save filharvey/d98bd2b20cd0a2c4403fab0a132000c5 to your computer and use it in GitHub Desktop.
Save filharvey/d98bd2b20cd0a2c4403fab0a132000c5 to your computer and use it in GitHub Desktop.
Exports a THREE.js scene mesh to STL, making it suitable for 3d printing
/**
* Based on https://github.com/mrdoob/three.js/blob/a72347515fa34e892f7a9bfa66a34fdc0df55954/examples/js/exporters/STLExporter.js
* extended from https://gist.github.com/kjlubick/fb6ba9c51df63ba0951f
* Tested on r68 and r70
* @author kjlubick / https://github.com/kjlubick
* @author kovacsv / http://kovacsv.hu/
* @author mrdoob / http://mrdoob.com/
*/
THREE.STLExporter = function () {};
THREE.STLExporter.prototype = {
constructor: THREE.STLExporter,
parse: ( function () {
var vector = new THREE.Vector3();
var normalMatrixWorld = new THREE.Matrix3();
return function ( scene ) {
var output = '';
output += 'solid exported\n';
scene.traverse( function ( object ) {
if ( object instanceof THREE.Mesh ) {
var geometry = object.geometry;
var skeleton = object.skeleton;
var matrixWorld = object.matrixWorld;
var mesh = object;
if (geometry instanceof THREE.BufferGeometry)
{
geometry = new THREE.Geometry().fromBufferGeometry( geometry );
}
if ( geometry instanceof THREE.Geometry ) {
var vertices = geometry.vertices;
var faces = geometry.faces;
normalMatrixWorld.getNormalMatrix( matrixWorld );
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
output += '\tfacet normal ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
output += '\t\touter loop\n';
var indices = [ face.a, face.b, face.c ];
for ( var j = 0; j < 3; j ++ ) {
var vertexIndex = indices[ j ];
if (geometry.skinIndices.length == 0) {
vector.copy( vertices[ vertexIndex ] ).applyMatrix4( matrixWorld );
output += '\t\t\tvertex ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
} else {
vector.copy( vertices[ vertexIndex ] ); //.applyMatrix4( matrixWorld );
// see https://github.com/mrdoob/three.js/issues/3187
boneIndices = [];
boneIndices[0] = geometry.skinIndices[vertexIndex].x;
boneIndices[1] = geometry.skinIndices[vertexIndex].y;
boneIndices[2] = geometry.skinIndices[vertexIndex].z;
boneIndices[3] = geometry.skinIndices[vertexIndex].w;
weights = [];
weights[0] = geometry.skinWeights[vertexIndex].x;
weights[1] = geometry.skinWeights[vertexIndex].y;
weights[2] = geometry.skinWeights[vertexIndex].z;
weights[3] = geometry.skinWeights[vertexIndex].w;
inverses = [];
inverses[0] = skeleton.boneInverses[ boneIndices[0] ];
inverses[1] = skeleton.boneInverses[ boneIndices[1] ];
inverses[2] = skeleton.boneInverses[ boneIndices[2] ];
inverses[3] = skeleton.boneInverses[ boneIndices[3] ];
skinMatrices = [];
skinMatrices[0] = skeleton.bones[ boneIndices[0] ].matrixWorld;
skinMatrices[1] = skeleton.bones[ boneIndices[1] ].matrixWorld;
skinMatrices[2] = skeleton.bones[ boneIndices[2] ].matrixWorld;
skinMatrices[3] = skeleton.bones[ boneIndices[3] ].matrixWorld;
var finalVector = new THREE.Vector4();
for(var k = 0; k<4; k++) {
var tempVector = new THREE.Vector4(vector.x, vector.y, vector.z);
tempVector.multiplyScalar(weights[k]);
//the inverse takes the vector into local bone space
tempVector.applyMatrix4(inverses[k])
//which is then transformed to the appropriate world space
.applyMatrix4(skinMatrices[k]);
finalVector.add(tempVector);
}
output += '\t\t\tvertex ' + finalVector.x + ' ' + finalVector.y + ' ' + finalVector.z + '\n';
}
}
output += '\t\tendloop\n';
output += '\tendfacet\n';
}
}
}
} );
output += 'endsolid exported\n';
return output;
};
}() )
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment