{"version":3,"file":"STLLoader.cjs","sources":["../../src/loaders/STLLoader.js"],"sourcesContent":["import {\n BufferAttribute,\n BufferGeometry,\n FileLoader,\n Float32BufferAttribute,\n Loader,\n LoaderUtils,\n Vector3,\n} from 'three'\nimport { decodeText } from '../_polyfill/LoaderUtils'\n\n/**\n * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs.\n *\n * Supports both binary and ASCII encoded files, with automatic detection of type.\n *\n * The loader returns a non-indexed buffer geometry.\n *\n * Limitations:\n * Binary decoding supports \"Magics\" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).\n * There is perhaps some question as to how valid it is to always assume little-endian-ness.\n * ASCII decoding assumes file is UTF-8.\n *\n * Usage:\n * const loader = new STLLoader();\n * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) {\n * scene.add( new THREE.Mesh( geometry ) );\n * });\n *\n * For binary STLs geometry might contain colors for vertices. To use it:\n * // use the same code to load STL as above\n * if (geometry.hasColors) {\n * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true });\n * } else { .... }\n * const mesh = new THREE.Mesh( geometry, material );\n *\n * For ASCII STLs containing multiple solids, each solid is assigned to a different group.\n * Groups can be used to assign a different color by defining an array of materials with the same length of\n * geometry.groups and passing it to the Mesh constructor:\n *\n * const mesh = new THREE.Mesh( geometry, material );\n *\n * For example:\n *\n * const materials = [];\n * const nGeometryGroups = geometry.groups.length;\n *\n * const colorMap = ...; // Some logic to index colors.\n *\n * for (let i = 0; i < nGeometryGroups; i++) {\n *\n *\t\tconst material = new THREE.MeshPhongMaterial({\n *\t\t\tcolor: colorMap[i],\n *\t\t\twireframe: false\n *\t\t});\n *\n * }\n *\n * materials.push(material);\n * const mesh = new THREE.Mesh(geometry, materials);\n */\n\nclass STLLoader extends Loader {\n constructor(manager) {\n super(manager)\n }\n\n load(url, onLoad, onProgress, onError) {\n const scope = this\n\n const loader = new FileLoader(this.manager)\n loader.setPath(this.path)\n loader.setResponseType('arraybuffer')\n loader.setRequestHeader(this.requestHeader)\n loader.setWithCredentials(this.withCredentials)\n\n loader.load(\n url,\n function (text) {\n try {\n onLoad(scope.parse(text))\n } catch (e) {\n if (onError) {\n onError(e)\n } else {\n console.error(e)\n }\n\n scope.manager.itemError(url)\n }\n },\n onProgress,\n onError,\n )\n }\n\n parse(data) {\n function isBinary(data) {\n const reader = new DataView(data)\n const face_size = (32 / 8) * 3 + (32 / 8) * 3 * 3 + 16 / 8\n const n_faces = reader.getUint32(80, true)\n const expect = 80 + 32 / 8 + n_faces * face_size\n\n if (expect === reader.byteLength) {\n return true\n }\n\n // An ASCII STL data must begin with 'solid ' as the first six bytes.\n // However, ASCII STLs lacking the SPACE after the 'd' are known to be\n // plentiful. So, check the first 5 bytes for 'solid'.\n\n // Several encodings, such as UTF-8, precede the text with up to 5 bytes:\n // https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding\n // Search for \"solid\" to start anywhere after those prefixes.\n\n // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'\n\n const solid = [115, 111, 108, 105, 100]\n\n for (let off = 0; off < 5; off++) {\n // If \"solid\" text is matched to the current offset, declare it to be an ASCII STL.\n\n if (matchDataViewAt(solid, reader, off)) return false\n }\n\n // Couldn't find \"solid\" text at the beginning; it is binary STL.\n\n return true\n }\n\n function matchDataViewAt(query, reader, offset) {\n // Check if each byte in query matches the corresponding byte from the current offset\n\n for (let i = 0, il = query.length; i < il; i++) {\n if (query[i] !== reader.getUint8(offset + i, false)) return false\n }\n\n return true\n }\n\n function parseBinary(data) {\n const reader = new DataView(data)\n const faces = reader.getUint32(80, true)\n\n let r,\n g,\n b,\n hasColors = false,\n colors\n let defaultR, defaultG, defaultB, alpha\n\n // process STL header\n // check for default color in header (\"COLOR=rgba\" sequence).\n\n for (let index = 0; index < 80 - 10; index++) {\n if (\n reader.getUint32(index, false) == 0x434f4c4f /*COLO*/ &&\n reader.getUint8(index + 4) == 0x52 /*'R'*/ &&\n reader.getUint8(index + 5) == 0x3d /*'='*/\n ) {\n hasColors = true\n colors = new Float32Array(faces * 3 * 3)\n\n defaultR = reader.getUint8(index + 6) / 255\n defaultG = reader.getUint8(index + 7) / 255\n defaultB = reader.getUint8(index + 8) / 255\n alpha = reader.getUint8(index + 9) / 255\n }\n }\n\n const dataOffset = 84\n const faceLength = 12 * 4 + 2\n\n const geometry = new BufferGeometry()\n\n const vertices = new Float32Array(faces * 3 * 3)\n const normals = new Float32Array(faces * 3 * 3)\n\n for (let face = 0; face < faces; face++) {\n const start = dataOffset + face * faceLength\n const normalX = reader.getFloat32(start, true)\n const normalY = reader.getFloat32(start + 4, true)\n const normalZ = reader.getFloat32(start + 8, true)\n\n if (hasColors) {\n const packedColor = reader.getUint16(start + 48, true)\n\n if ((packedColor & 0x8000) === 0) {\n // facet has its own unique color\n\n r = (packedColor & 0x1f) / 31\n g = ((packedColor >> 5) & 0x1f) / 31\n b = ((packedColor >> 10) & 0x1f) / 31\n } else {\n r = defaultR\n g = defaultG\n b = defaultB\n }\n }\n\n for (let i = 1; i <= 3; i++) {\n const vertexstart = start + i * 12\n const componentIdx = face * 3 * 3 + (i - 1) * 3\n\n vertices[componentIdx] = reader.getFloat32(vertexstart, true)\n vertices[componentIdx + 1] = reader.getFloat32(vertexstart + 4, true)\n vertices[componentIdx + 2] = reader.getFloat32(vertexstart + 8, true)\n\n normals[componentIdx] = normalX\n normals[componentIdx + 1] = normalY\n normals[componentIdx + 2] = normalZ\n\n if (hasColors) {\n colors[componentIdx] = r\n colors[componentIdx + 1] = g\n colors[componentIdx + 2] = b\n }\n }\n }\n\n geometry.setAttribute('position', new BufferAttribute(vertices, 3))\n geometry.setAttribute('normal', new BufferAttribute(normals, 3))\n\n if (hasColors) {\n geometry.setAttribute('color', new BufferAttribute(colors, 3))\n geometry.hasColors = true\n geometry.alpha = alpha\n }\n\n return geometry\n }\n\n function parseASCII(data) {\n const geometry = new BufferGeometry()\n const patternSolid = /solid([\\s\\S]*?)endsolid/g\n const patternFace = /facet([\\s\\S]*?)endfacet/g\n let faceCounter = 0\n\n const patternFloat = /[\\s]+([+-]?(?:\\d*)(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)/.source\n const patternVertex = new RegExp('vertex' + patternFloat + patternFloat + patternFloat, 'g')\n const patternNormal = new RegExp('normal' + patternFloat + patternFloat + patternFloat, 'g')\n\n const vertices = []\n const normals = []\n\n const normal = new Vector3()\n\n let result\n\n let groupCount = 0\n let startVertex = 0\n let endVertex = 0\n\n while ((result = patternSolid.exec(data)) !== null) {\n startVertex = endVertex\n\n const solid = result[0]\n\n while ((result = patternFace.exec(solid)) !== null) {\n let vertexCountPerFace = 0\n let normalCountPerFace = 0\n\n const text = result[0]\n\n while ((result = patternNormal.exec(text)) !== null) {\n normal.x = parseFloat(result[1])\n normal.y = parseFloat(result[2])\n normal.z = parseFloat(result[3])\n normalCountPerFace++\n }\n\n while ((result = patternVertex.exec(text)) !== null) {\n vertices.push(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]))\n normals.push(normal.x, normal.y, normal.z)\n vertexCountPerFace++\n endVertex++\n }\n\n // every face have to own ONE valid normal\n\n if (normalCountPerFace !== 1) {\n console.error(\"THREE.STLLoader: Something isn't right with the normal of face number \" + faceCounter)\n }\n\n // each face have to own THREE valid vertices\n\n if (vertexCountPerFace !== 3) {\n console.error(\"THREE.STLLoader: Something isn't right with the vertices of face number \" + faceCounter)\n }\n\n faceCounter++\n }\n\n const start = startVertex\n const count = endVertex - startVertex\n\n geometry.addGroup(start, count, groupCount)\n groupCount++\n }\n\n geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3))\n geometry.setAttribute('normal', new Float32BufferAttribute(normals, 3))\n\n return geometry\n }\n\n function ensureString(buffer) {\n if (typeof buffer !== 'string') {\n return decodeText(new Uint8Array(buffer))\n }\n\n return buffer\n }\n\n function ensureBinary(buffer) {\n if (typeof buffer === 'string') {\n const array_buffer = new Uint8Array(buffer.length)\n for (let i = 0; i < buffer.length; i++) {\n array_buffer[i] = buffer.charCodeAt(i) & 0xff // implicitly assumes little-endian\n }\n\n return array_buffer.buffer || array_buffer\n } else {\n return buffer\n }\n }\n\n // start\n\n const binData = ensureBinary(data)\n\n return isBinary(binData) ? parseBinary(binData) : parseASCII(ensureString(data))\n }\n}\n\nexport { STLLoader }\n"],"names":["Loader","FileLoader","data","BufferGeometry","BufferAttribute","Vector3","Float32BufferAttribute","decodeText"],"mappings":";;;;AA8DA,MAAM,kBAAkBA,MAAAA,OAAO;AAAA,EAC7B,YAAY,SAAS;AACnB,UAAM,OAAO;AAAA,EACd;AAAA,EAED,KAAK,KAAK,QAAQ,YAAY,SAAS;AACrC,UAAM,QAAQ;AAEd,UAAM,SAAS,IAAIC,iBAAW,KAAK,OAAO;AAC1C,WAAO,QAAQ,KAAK,IAAI;AACxB,WAAO,gBAAgB,aAAa;AACpC,WAAO,iBAAiB,KAAK,aAAa;AAC1C,WAAO,mBAAmB,KAAK,eAAe;AAE9C,WAAO;AAAA,MACL;AAAA,MACA,SAAU,MAAM;AACd,YAAI;AACF,iBAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QACzB,SAAQ,GAAP;AACA,cAAI,SAAS;AACX,oBAAQ,CAAC;AAAA,UACrB,OAAiB;AACL,oBAAQ,MAAM,CAAC;AAAA,UAChB;AAED,gBAAM,QAAQ,UAAU,GAAG;AAAA,QAC5B;AAAA,MACF;AAAA,MACD;AAAA,MACA;AAAA,IACD;AAAA,EACF;AAAA,EAED,MAAM,MAAM;AACV,aAAS,SAASC,OAAM;AACtB,YAAM,SAAS,IAAI,SAASA,KAAI;AAChC,YAAM,YAAa,KAAK,IAAK,IAAK,KAAK,IAAK,IAAI,IAAI,KAAK;AACzD,YAAM,UAAU,OAAO,UAAU,IAAI,IAAI;AACzC,YAAM,SAAS,KAAK,KAAK,IAAI,UAAU;AAEvC,UAAI,WAAW,OAAO,YAAY;AAChC,eAAO;AAAA,MACR;AAYD,YAAM,QAAQ,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAEtC,eAAS,MAAM,GAAG,MAAM,GAAG,OAAO;AAGhC,YAAI,gBAAgB,OAAO,QAAQ,GAAG;AAAG,iBAAO;AAAA,MACjD;AAID,aAAO;AAAA,IACR;AAED,aAAS,gBAAgB,OAAO,QAAQ,QAAQ;AAG9C,eAAS,IAAI,GAAG,KAAK,MAAM,QAAQ,IAAI,IAAI,KAAK;AAC9C,YAAI,MAAM,CAAC,MAAM,OAAO,SAAS,SAAS,GAAG,KAAK;AAAG,iBAAO;AAAA,MAC7D;AAED,aAAO;AAAA,IACR;AAED,aAAS,YAAYA,OAAM;AACzB,YAAM,SAAS,IAAI,SAASA,KAAI;AAChC,YAAM,QAAQ,OAAO,UAAU,IAAI,IAAI;AAEvC,UAAI,GACF,GACA,GACA,YAAY,OACZ;AACF,UAAI,UAAU,UAAU,UAAU;AAKlC,eAAS,QAAQ,GAAG,QAAQ,KAAK,IAAI,SAAS;AAC5C,YACE,OAAO,UAAU,OAAO,KAAK,KAAK,cAClC,OAAO,SAAS,QAAQ,CAAC,KAAK,MAC9B,OAAO,SAAS,QAAQ,CAAC,KAAK,IAC9B;AACA,sBAAY;AACZ,mBAAS,IAAI,aAAa,QAAQ,IAAI,CAAC;AAEvC,qBAAW,OAAO,SAAS,QAAQ,CAAC,IAAI;AACxC,qBAAW,OAAO,SAAS,QAAQ,CAAC,IAAI;AACxC,qBAAW,OAAO,SAAS,QAAQ,CAAC,IAAI;AACxC,kBAAQ,OAAO,SAAS,QAAQ,CAAC,IAAI;AAAA,QACtC;AAAA,MACF;AAED,YAAM,aAAa;AACnB,YAAM,aAAa,KAAK,IAAI;AAE5B,YAAM,WAAW,IAAIC,qBAAgB;AAErC,YAAM,WAAW,IAAI,aAAa,QAAQ,IAAI,CAAC;AAC/C,YAAM,UAAU,IAAI,aAAa,QAAQ,IAAI,CAAC;AAE9C,eAAS,OAAO,GAAG,OAAO,OAAO,QAAQ;AACvC,cAAM,QAAQ,aAAa,OAAO;AAClC,cAAM,UAAU,OAAO,WAAW,OAAO,IAAI;AAC7C,cAAM,UAAU,OAAO,WAAW,QAAQ,GAAG,IAAI;AACjD,cAAM,UAAU,OAAO,WAAW,QAAQ,GAAG,IAAI;AAEjD,YAAI,WAAW;AACb,gBAAM,cAAc,OAAO,UAAU,QAAQ,IAAI,IAAI;AAErD,eAAK,cAAc,WAAY,GAAG;AAGhC,iBAAK,cAAc,MAAQ;AAC3B,iBAAM,eAAe,IAAK,MAAQ;AAClC,iBAAM,eAAe,KAAM,MAAQ;AAAA,UAC/C,OAAiB;AACL,gBAAI;AACJ,gBAAI;AACJ,gBAAI;AAAA,UACL;AAAA,QACF;AAED,iBAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,gBAAM,cAAc,QAAQ,IAAI;AAChC,gBAAM,eAAe,OAAO,IAAI,KAAK,IAAI,KAAK;AAE9C,mBAAS,YAAY,IAAI,OAAO,WAAW,aAAa,IAAI;AAC5D,mBAAS,eAAe,CAAC,IAAI,OAAO,WAAW,cAAc,GAAG,IAAI;AACpE,mBAAS,eAAe,CAAC,IAAI,OAAO,WAAW,cAAc,GAAG,IAAI;AAEpE,kBAAQ,YAAY,IAAI;AACxB,kBAAQ,eAAe,CAAC,IAAI;AAC5B,kBAAQ,eAAe,CAAC,IAAI;AAE5B,cAAI,WAAW;AACb,mBAAO,YAAY,IAAI;AACvB,mBAAO,eAAe,CAAC,IAAI;AAC3B,mBAAO,eAAe,CAAC,IAAI;AAAA,UAC5B;AAAA,QACF;AAAA,MACF;AAED,eAAS,aAAa,YAAY,IAAIC,MAAAA,gBAAgB,UAAU,CAAC,CAAC;AAClE,eAAS,aAAa,UAAU,IAAIA,MAAAA,gBAAgB,SAAS,CAAC,CAAC;AAE/D,UAAI,WAAW;AACb,iBAAS,aAAa,SAAS,IAAIA,MAAAA,gBAAgB,QAAQ,CAAC,CAAC;AAC7D,iBAAS,YAAY;AACrB,iBAAS,QAAQ;AAAA,MAClB;AAED,aAAO;AAAA,IACR;AAED,aAAS,WAAWF,OAAM;AACxB,YAAM,WAAW,IAAIC,qBAAgB;AACrC,YAAM,eAAe;AACrB,YAAM,cAAc;AACpB,UAAI,cAAc;AAElB,YAAM,eAAe,iDAAiD;AACtE,YAAM,gBAAgB,IAAI,OAAO,WAAW,eAAe,eAAe,cAAc,GAAG;AAC3F,YAAM,gBAAgB,IAAI,OAAO,WAAW,eAAe,eAAe,cAAc,GAAG;AAE3F,YAAM,WAAW,CAAE;AACnB,YAAM,UAAU,CAAE;AAElB,YAAM,SAAS,IAAIE,cAAS;AAE5B,UAAI;AAEJ,UAAI,aAAa;AACjB,UAAI,cAAc;AAClB,UAAI,YAAY;AAEhB,cAAQ,SAAS,aAAa,KAAKH,KAAI,OAAO,MAAM;AAClD,sBAAc;AAEd,cAAM,QAAQ,OAAO,CAAC;AAEtB,gBAAQ,SAAS,YAAY,KAAK,KAAK,OAAO,MAAM;AAClD,cAAI,qBAAqB;AACzB,cAAI,qBAAqB;AAEzB,gBAAM,OAAO,OAAO,CAAC;AAErB,kBAAQ,SAAS,cAAc,KAAK,IAAI,OAAO,MAAM;AACnD,mBAAO,IAAI,WAAW,OAAO,CAAC,CAAC;AAC/B,mBAAO,IAAI,WAAW,OAAO,CAAC,CAAC;AAC/B,mBAAO,IAAI,WAAW,OAAO,CAAC,CAAC;AAC/B;AAAA,UACD;AAED,kBAAQ,SAAS,cAAc,KAAK,IAAI,OAAO,MAAM;AACnD,qBAAS,KAAK,WAAW,OAAO,CAAC,CAAC,GAAG,WAAW,OAAO,CAAC,CAAC,GAAG,WAAW,OAAO,CAAC,CAAC,CAAC;AACjF,oBAAQ,KAAK,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AACzC;AACA;AAAA,UACD;AAID,cAAI,uBAAuB,GAAG;AAC5B,oBAAQ,MAAM,2EAA2E,WAAW;AAAA,UACrG;AAID,cAAI,uBAAuB,GAAG;AAC5B,oBAAQ,MAAM,6EAA6E,WAAW;AAAA,UACvG;AAED;AAAA,QACD;AAED,cAAM,QAAQ;AACd,cAAM,QAAQ,YAAY;AAE1B,iBAAS,SAAS,OAAO,OAAO,UAAU;AAC1C;AAAA,MACD;AAED,eAAS,aAAa,YAAY,IAAII,MAAAA,uBAAuB,UAAU,CAAC,CAAC;AACzE,eAAS,aAAa,UAAU,IAAIA,MAAAA,uBAAuB,SAAS,CAAC,CAAC;AAEtE,aAAO;AAAA,IACR;AAED,aAAS,aAAa,QAAQ;AAC5B,UAAI,OAAO,WAAW,UAAU;AAC9B,eAAOC,uBAAW,IAAI,WAAW,MAAM,CAAC;AAAA,MACzC;AAED,aAAO;AAAA,IACR;AAED,aAAS,aAAa,QAAQ;AAC5B,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,eAAe,IAAI,WAAW,OAAO,MAAM;AACjD,iBAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,uBAAa,CAAC,IAAI,OAAO,WAAW,CAAC,IAAI;AAAA,QAC1C;AAED,eAAO,aAAa,UAAU;AAAA,MACtC,OAAa;AACL,eAAO;AAAA,MACR;AAAA,IACF;AAID,UAAM,UAAU,aAAa,IAAI;AAEjC,WAAO,SAAS,OAAO,IAAI,YAAY,OAAO,IAAI,WAAW,aAAa,IAAI,CAAC;AAAA,EAChF;AACH;;"}