123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- import { Vector3 } from '../lib/three.module.js'
- /**
- * Usage:
- * const exporter = new STLExporter();
- *
- * // second argument is a list of options
- * const data = exporter.parse( mesh, { binary: true } );
- *
- */
- class STLExporter {
- parse(scene, options = {}) {
- const binary = options.binary !== undefined ? options.binary : false
- //
- const objects = []
- let triangles = 0
- scene.traverse(function(object) {
- if (object.isMesh && object.visible) {
- const geometry = object.geometry
- if (geometry.isBufferGeometry !== true) {
- throw new Error('THREE.STLExporter: Geometry is not of type THREE.BufferGeometry.')
- }
- const index = geometry.index
- const positionAttribute = geometry.getAttribute('position')
- triangles += index !== null ? index.count / 3 : positionAttribute.count / 3
- objects.push({
- object3d: object,
- geometry: geometry
- })
- }
- })
- let output
- let offset = 80 // skip header
- if (binary === true) {
- const bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4
- const arrayBuffer = new ArrayBuffer(bufferLength)
- output = new DataView(arrayBuffer)
- output.setUint32(offset, triangles, true)
- offset += 4
- } else {
- output = ''
- output += 'solid exported\n'
- }
- const vA = new Vector3()
- const vB = new Vector3()
- const vC = new Vector3()
- const cb = new Vector3()
- const ab = new Vector3()
- const normal = new Vector3()
- for (let i = 0, il = objects.length; i < il; i++) {
- const object = objects[i].object3d
- const geometry = objects[i].geometry
- const index = geometry.index
- const positionAttribute = geometry.getAttribute('position')
- if (index !== null) {
- // indexed geometry
- for (let j = 0; j < index.count; j += 3) {
- const a = index.getX(j + 0)
- const b = index.getX(j + 1)
- const c = index.getX(j + 2)
- writeFace(a, b, c, positionAttribute, object)
- }
- } else {
- // non-indexed geometry
- for (let j = 0; j < positionAttribute.count; j += 3) {
- const a = j + 0
- const b = j + 1
- const c = j + 2
- writeFace(a, b, c, positionAttribute, object)
- }
- }
- }
- if (binary === false) {
- output += 'endsolid exported\n'
- }
- return output
- function writeFace(a, b, c, positionAttribute, object) {
- vA.fromBufferAttribute(positionAttribute, a)
- vB.fromBufferAttribute(positionAttribute, b)
- vC.fromBufferAttribute(positionAttribute, c)
- if (object.isSkinnedMesh === true) {
- object.boneTransform(a, vA)
- object.boneTransform(b, vB)
- object.boneTransform(c, vC)
- }
- vA.applyMatrix4(object.matrixWorld)
- vB.applyMatrix4(object.matrixWorld)
- vC.applyMatrix4(object.matrixWorld)
- writeNormal(vA, vB, vC)
- writeVertex(vA)
- writeVertex(vB)
- writeVertex(vC)
- if (binary === true) {
- output.setUint16(offset, 0, true)
- offset += 2
- } else {
- output += '\t\tendloop\n'
- output += '\tendfacet\n'
- }
- }
- function writeNormal(vA, vB, vC) {
- cb.subVectors(vC, vB)
- ab.subVectors(vA, vB)
- cb.cross(ab).normalize()
- normal.copy(cb).normalize()
- if (binary === true) {
- output.setFloat32(offset, normal.x, true)
- offset += 4
- output.setFloat32(offset, normal.y, true)
- offset += 4
- output.setFloat32(offset, normal.z, true)
- offset += 4
- } else {
- output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'
- output += '\t\touter loop\n'
- }
- }
- function writeVertex(vertex) {
- if (binary === true) {
- output.setFloat32(offset, vertex.x, true)
- offset += 4
- output.setFloat32(offset, vertex.y, true)
- offset += 4
- output.setFloat32(offset, vertex.z, true)
- offset += 4
- } else {
- output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'
- }
- }
- }
- }
- export { STLExporter }
|