import { Mesh } from "./mesh.js"
import { Triangle } from "./triangle.js"
import { Vector } from "./vector.js"
/**https://github.com/amandaghassaei/stl-parser/blob/main/src/stl-parser.ts
*
*/
/*
from https://en.wikipedia.org/wiki/STL_(file_format)
UINT8[80] – Header - 80 bytes
UINT32 – Number of triangles - 04 bytes
foreach triangle - 50 bytes
REAL32[3] – Normal vector - 12 bytes
REAL32[3] – Vertex 1 - 12 bytes
REAL32[3] – Vertex 2 - 12 bytes
REAL32[3] – Vertex 3 - 12 bytes
UINT16 – Attribute byte count - 02 bytes
end
*/
/**
* Loads a model from binary STL file
* @param {String} path
* @returns {Mesh}
*/
export async function loadBinaryStl(path) {
const response = await fetch(path)
const arrayBuffer = await response.arrayBuffer()
let faceCount = new Uint8Array(arrayBuffer)[80] // header ends at 80
const buffer = new DataView(arrayBuffer)
console.log(buffer)
let offset = 84
let triDataLength = 12 * 4 + 2///each tri is 50 bytes
let tris = []
for (let i = 0; i < faceCount; i++) {
let tri = []
for (let j = 1; j <= 3; j++) {
const vertexStart = start + j * 12
let vert = new Vector()
vert.x = buffer.getFloat32(vertexStart, true)
vert.y = buffer.getFloat32(vertexStart + 4, true)
vert.z = buffer.getFloat32(vertexStart + 8, true)
tri.push(vert)
}
tri = new Triangle(tri[0], tri[1], tri[2])
tris.push(tri)
}
// console.log(tris)
return new Mesh(tris)
}
/**
* exports selected mesh as STL
* @param {Mesh} mesh to be output
*
*/
export function saveBinaryStl(mesh) {
let size = mesh.triangles.length*50+84
let buffer = new DataView(new ArrayBuffer(size))
/// write header, write verts to buffer
buffer.setUint32(80, mesh.triangles.length, true)
let offset = 84
let triDataLength = 12 * 4 + 2///each tri is 50 bytes
for (let i = 0; i < mesh.triangles.length; i++) {
let start = offset + (i * triDataLength)/////start at 84+50*i to loop though each tri skipping normal
let tri = mesh.triangles[i]
for (let j = 1; j <= 3; j++) {
/// should probably write normals to the file, but eh, nah
const vertexStart = start + j * 12
let vert
if(j==1)vert= tri.v1
if(j==2)vert = tri.v2
if (j==3)vert = tri.v3//this aint pretty but it a works a
console.log(tri)
buffer.setFloat32(vertexStart,vert.x,true)
buffer.setFloat32(vertexStart+4,vert.y,true)
buffer.setFloat32(vertexStart+8,vert.z,true)
}
}
const blob = new Blob([buffer], { type: 'application' });
// 2. Create an anchor element
const link = document.createElement("a");
// 3. Create a URL for the blob and set it as the download target
link.href = URL.createObjectURL(blob);
link.download = "model.stl";
// 4. Trigger the download
document.body.appendChild(link);
link.click();
// 5. Cleanup
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
}
/**
* Loads a model from text STL file
* @param {String} path
* @returns {Mesh}
*/
export async function loadTextSTL(path) {
const response = await fetch(path).then(r => r.text())
const lines = response.split('\n');
let tris = []
let tri = []
for (let line of lines) {
let parts = line.trim().split(/\s+/)
if (parts[0] == "vertex") {
let vert = new Vector(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3]))
tri.push(vert)
if (tri.length == 3) {
tris.push(new Triangle(tri[0], tri[1], tri[2]))
tri = []
}
}
}
return new Mesh(tris)
}