UNPKG

@toybox-labs/cura-wasm

Version:

Cura Engine powered by Web Assembly (WASM)

118 lines (100 loc) 3.81 kB
/** * @fileoverview File Utilities */ //Imports import {FileFormats, Unified3dLoader} from 'unified-3d-loader'; /** * Convert a pair of vertices and normals to a binary STL * @param normals The STL normals * @param vertices The STL vertices (Should be 3x the length of the normals) */ export const meshToSTL = (normals: number[], vertices: number[]): ArrayBuffer => { //Create a binary STL const length = 84 + (50 * normals.length); const buffer = new ArrayBuffer(length); const dataView = new DataView(buffer); //Set face count dataView.setUint32(80, normals.length, true); //Iterate over each face for (let face = 0; face < normals.length / 3; face++) { //Get current offsets const binaryOffset = 84 + (50 * face); const normalOffset = 3 * face; const verticeOffset = 9 * face; //Set the normal dataView.setFloat32(binaryOffset, normals[normalOffset], true); dataView.setFloat32(binaryOffset + 4, normals[normalOffset + 1], true); dataView.setFloat32(binaryOffset + 8, normals[normalOffset + 2], true); //Set the first vertex dataView.setFloat32(binaryOffset + 12, vertices[verticeOffset], true); dataView.setFloat32(binaryOffset + 16, vertices[verticeOffset + 1], true); dataView.setFloat32(binaryOffset + 20, vertices[verticeOffset + 2], true); //Set the second vertex dataView.setFloat32(binaryOffset + 24, vertices[verticeOffset + 3], true); dataView.setFloat32(binaryOffset + 28, vertices[verticeOffset + 4], true); dataView.setFloat32(binaryOffset + 32, vertices[verticeOffset + 5], true); //Set the third vertex dataView.setFloat32(binaryOffset + 36, vertices[verticeOffset + 6], true); dataView.setFloat32(binaryOffset + 40, vertices[verticeOffset + 7], true); dataView.setFloat32(binaryOffset + 44, vertices[verticeOffset + 8], true); } return buffer; }; /** * Convert a 3D file to an STL * @param file The file * @param extension The file extension * @param progress The progress event handler */ export const convert = async (file: ArrayBuffer, extension: string, progress: (progress: number) => void): Promise<Uint8Array | Error> => { //Get the unified-3d-loader file format const format = Object.values(FileFormats).find(format => format.extensions.includes(extension)); //If an STL, bypass unified-3d-loader if (extension == 'stl') { return new Uint8Array(file); } //If unified-3d-loader is capable of parsing the file, use it else if (format != null) { //Parse/load const parser = new Unified3dLoader(); parser.on('progress', (loaderProgress: number) => { progress(loaderProgress / 100); }); const meshes = await parser.load(file, format, { index: { normals: false, vertices: false } }); //Convert to a binary STL if (meshes.length == 0) { return new Error('[Unified-3D-Loader] Got 0 meshes when parsing the supplied file!'); } else { //Warn about multiple meshes if (meshes.length > 1) { console.warn(`[Unified-3D-Loader] Got ${meshes.length} meshes when parsing the user supplied file, using the first one! (Some features may be disabled!)`); } //@ts-ignore Unified-3D-Loader will return a numeric array if the normal index setting is false const normals: number[] = meshes[0].normals; //@ts-ignore Unified-3D-Loader will return a numeric array if the vertice index setting is false const vertices: number[] = meshes[0].vertices; //Convert the ArrayBuffer STL to a Uint8Array const stl = meshToSTL(normals, vertices); return new Uint8Array(stl); } } else { return new Error(`[Unified-3D-Loader] Unable to parse file with extension: ${extension}`); } };