* The `saveStl()` function exports `p5.Geometry` objects as * 3D models in the STL stereolithography file format. * This way, you can use the 3D shapes you create in p5.js in other software * for rendering, animation, 3D printing, or more. * * The exported .stl file will include the f
(fileName = 'model.stl', { binary = false } = {})
| 464 | * } |
| 465 | */ |
| 466 | saveStl(fileName = 'model.stl', { binary = false } = {}){ |
| 467 | let modelOutput; |
| 468 | let name = fileName.substring(0, fileName.lastIndexOf('.')); |
| 469 | let faceNormals = []; |
| 470 | for (let f of this.faces) { |
| 471 | const U = Vector.sub(this.vertices[f[1]], this.vertices[f[0]]); |
| 472 | const V = Vector.sub(this.vertices[f[2]], this.vertices[f[0]]); |
| 473 | const nx = U.y * V.z - U.z * V.y; |
| 474 | const ny = U.z * V.x - U.x * V.z; |
| 475 | const nz = U.x * V.y - U.y * V.x; |
| 476 | faceNormals.push(new Vector(nx, ny, nz).normalize()); |
| 477 | } |
| 478 | if (binary) { |
| 479 | let offset = 80; |
| 480 | const bufferLength = |
| 481 | this.faces.length * 2 + this.faces.length * 3 * 4 * 4 + 80 + 4; |
| 482 | const arrayBuffer = new ArrayBuffer(bufferLength); |
| 483 | modelOutput = new DataView(arrayBuffer); |
| 484 | modelOutput.setUint32(offset, this.faces.length, true); |
| 485 | offset += 4; |
| 486 | for (const [key, f] of Object.entries(this.faces)) { |
| 487 | const norm = faceNormals[key]; |
| 488 | modelOutput.setFloat32(offset, norm.x, true); |
| 489 | offset += 4; |
| 490 | modelOutput.setFloat32(offset, norm.y, true); |
| 491 | offset += 4; |
| 492 | modelOutput.setFloat32(offset, norm.z, true); |
| 493 | offset += 4; |
| 494 | for (let vertexIndex of f) { |
| 495 | const vert = this.vertices[vertexIndex]; |
| 496 | modelOutput.setFloat32(offset, vert.x, true); |
| 497 | offset += 4; |
| 498 | modelOutput.setFloat32(offset, vert.y, true); |
| 499 | offset += 4; |
| 500 | modelOutput.setFloat32(offset, vert.z, true); |
| 501 | offset += 4; |
| 502 | } |
| 503 | modelOutput.setUint16(offset, 0, true); |
| 504 | offset += 2; |
| 505 | } |
| 506 | } else { |
| 507 | modelOutput = 'solid ' + name + '\n'; |
| 508 | |
| 509 | for (const [key, f] of Object.entries(this.faces)) { |
| 510 | const norm = faceNormals[key]; |
| 511 | modelOutput += |
| 512 | ' facet norm ' + norm.x + ' ' + norm.y + ' ' + norm.z + '\n'; |
| 513 | modelOutput += ' outer loop' + '\n'; |
| 514 | for (let vertexIndex of f) { |
| 515 | const vert = this.vertices[vertexIndex]; |
| 516 | modelOutput += |
| 517 | ' vertex ' + vert.x + ' ' + vert.y + ' ' + vert.z + '\n'; |
| 518 | } |
| 519 | modelOutput += ' endloop' + '\n'; |
| 520 | modelOutput += ' endfacet' + '\n'; |
| 521 | } |
| 522 | modelOutput += 'endsolid ' + name + '\n'; |
| 523 | } |
nothing calls this directly
no test coverage detected