Blame view
js/threejs/STLExport.js
7.88 KB
670b6d6f8
![]() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
/** * Based on https://github.com/mrdoob/three.js/blob/a72347515fa34e892f7a9bfa66a34fdc0df55954/examples/js/exporters/STLExporter.js * Tested on r68 and r70 * @author jcarletto / https://github.com/jcarletto27 * @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 '; scene.traverse(function (object) { if (object instanceof THREE.Mesh) { var geometry = object.geometry; var matrixWorld = object.matrixWorld; var mesh = object; if (geometry instanceof THREE.Geometry) { var vertices = geometry.vertices; var faces = geometry.faces; normalMatrixWorld.getNormalMatrix(matrixWorld); console.log(faces); 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 + ' '; output += '\t\touter loop '; var indices = [face.a, face.b, face.c]; for (var j = 0; j < 3; j++) { var vertexIndex = indices[j]; if (mesh.geometry.skinIndices.length == 0) { vector.copy(vertices[vertexIndex]).applyMatrix4(matrixWorld); output += '\t\t\tvertex ' + vector.x + ' ' + vector.y + ' ' + vector.z + ' '; } else { vector.copy(vertices[vertexIndex]); //.applyMatrix4( matrixWorld ); // see https://github.com/mrdoob/three.js/issues/3187 boneIndices = []; boneIndices[0] = mesh.geometry.skinIndices[vertexIndex].x; boneIndices[1] = mesh.geometry.skinIndices[vertexIndex].y; boneIndices[2] = mesh.geometry.skinIndices[vertexIndex].z; boneIndices[3] = mesh.geometry.skinIndices[vertexIndex].w; weights = []; weights[0] = mesh.geometry.skinWeights[vertexIndex].x; weights[1] = mesh.geometry.skinWeights[vertexIndex].y; weights[2] = mesh.geometry.skinWeights[vertexIndex].z; weights[3] = mesh.geometry.skinWeights[vertexIndex].w; inverses = []; inverses[0] = mesh.skeleton.boneInverses[boneIndices[0]]; inverses[1] = mesh.skeleton.boneInverses[boneIndices[1]]; inverses[2] = mesh.skeleton.boneInverses[boneIndices[2]]; inverses[3] = mesh.skeleton.boneInverses[boneIndices[3]]; skinMatrices = []; skinMatrices[0] = mesh.skeleton.bones[boneIndices[0]].matrixWorld; skinMatrices[1] = mesh.skeleton.bones[boneIndices[1]].matrixWorld; skinMatrices[2] = mesh.skeleton.bones[boneIndices[2]].matrixWorld; skinMatrices[3] = mesh.skeleton.bones[boneIndices[3]].matrixWorld; //this checks to see if the mesh has any morphTargets - jc if (mesh.geometry.morphTargets !== 'undefined') { morphMatricesX = []; morphMatricesY = []; morphMatricesZ = []; morphMatricesInfluence = []; for (var mt = 0; mt < mesh.geometry.morphTargets.length; mt++) { //collect the needed vertex info - jc morphMatricesX[mt] = mesh.geometry.morphTargets[mt].vertices[vertexIndex].x; morphMatricesY[mt] = mesh.geometry.morphTargets[mt].vertices[vertexIndex].y; morphMatricesZ[mt] = mesh.geometry.morphTargets[mt].vertices[vertexIndex].z; morphMatricesInfluence[mt] = mesh.morphTargetInfluences[mt]; } } var finalVector = new THREE.Vector4(); if (mesh.geometry.morphTargets !== 'undefined') { var morphVector = new THREE.Vector4(vector.x, vector.y, vector.z); for (var mt = 0; mt < mesh.geometry.morphTargets.length; mt++) { //not pretty, but it gets the job done - jc morphVector.lerp(new THREE.Vector4(morphMatricesX[mt], morphMatricesY[mt], morphMatricesZ[mt], 1), morphMatricesInfluence[mt]); } } for (var k = 0; k < 4; k++) { if (mesh.geometry.morphTargets !== 'undefined') { var tempVector = new THREE.Vector4(morphVector.x, morphVector.y, morphVector.z); } else { var tempVector = new THREE.Vector4(vector.x, vector.y, vector.z); } tempVector.multiplyScalar(weights[k]); //the inverse takes the vector into local bone space //which is then transformed to the appropriate world space tempVector.applyMatrix4(inverses[k]) .applyMatrix4(skinMatrices[k]); finalVector.add(tempVector); } output += '\t\t\tvertex ' + finalVector.x + ' ' + finalVector.y + ' ' + finalVector.z + ' '; } } output += '\t\tendloop '; output += '\tendfacet '; } } } }); output += 'endsolid exported '; return output; }; } ()) }; function saveSTL(scene, name) { var exporter = new THREE.STLExporter(); var stlString = exporter.parse(scene); var blob = new Blob([stlString], { type: 'text/plain' }); saveAs(blob, name + '.stl'); } var exporter = new THREE.STLExporter(); var exportString = function (output, filename) { var blob = new Blob([output], { type: 'text/plain' }); var objectURL = URL.createObjectURL(blob); var link = document.createElement('a'); link.href = objectURL; link.download = filename || 'data.json'; link.target = '_blank'; link.click(); }; |