{"_id":"3d-file-parsers","name":"3d-file-parsers","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"3d-file-parsers","version":"1.0.0","description":"Lightweight, zero-dependency parsers for niche 3D file formats (M3D, X3D, IrrMesh, Terragen, PTS) that major libraries don't support. Returns raw typed arrays — works with Three.js, Babylon.js, or any WebGL framework.","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./m3d":{"import":{"types":"./dist/parsers/m3d.d.ts","default":"./dist/parsers/m3d.js"},"require":{"types":"./dist/parsers/m3d.d.cts","default":"./dist/parsers/m3d.cjs"}},"./x3d":{"import":{"types":"./dist/parsers/x3d.d.ts","default":"./dist/parsers/x3d.js"},"require":{"types":"./dist/parsers/x3d.d.cts","default":"./dist/parsers/x3d.cjs"}},"./irrmesh":{"import":{"types":"./dist/parsers/irrmesh.d.ts","default":"./dist/parsers/irrmesh.js"},"require":{"types":"./dist/parsers/irrmesh.d.cts","default":"./dist/parsers/irrmesh.cjs"}},"./terragen":{"import":{"types":"./dist/parsers/terragen.d.ts","default":"./dist/parsers/terragen.js"},"require":{"types":"./dist/parsers/terragen.d.cts","default":"./dist/parsers/terragen.cjs"}},"./pts":{"import":{"types":"./dist/parsers/pts.d.ts","default":"./dist/parsers/pts.js"},"require":{"types":"./dist/parsers/pts.d.cts","default":"./dist/parsers/pts.cjs"}}},"scripts":{"build":"tsup","prepublishOnly":"pnpm build"},"keywords":["3d","parser","m3d","x3d","irrmesh","irrlicht","terragen","pts","point-cloud","mesh","webgl","threejs","babylonjs","file-format","3d-converter","typed-array","browser","wasm"],"author":{"name":"FabRapid","email":"dev@fabrapid.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ROTFEAT/3d-file-parsers.git"},"homepage":"https://3d-tools.fabrapid.com","bugs":{"url":"https://github.com/ROTFEAT/3d-file-parsers/issues"},"dependencies":{"fflate":"^0.8.2"},"devDependencies":{"tsup":"^8.4.0","typescript":"^5.7.0"},"_id":"3d-file-parsers@1.0.0","gitHead":"28a44760ddc1ecb4695d5a3fb123f35dd0b6eb8b","_nodeVersion":"22.17.0","_npmVersion":"11.5.2","dist":{"integrity":"sha512-b8/1oOs07gavMzssX/QqpgCfc2gJIw+xYTp/4ySUZAY2ouYfOLbUXKE1AZmzwo4Pje8H2JjVuKC9Tj+pzi7LSA==","shasum":"de3bcd8cc635daf1e76fc6c6b8d44195f144d009","tarball":"https://registry.npmjs.org/3d-file-parsers/-/3d-file-parsers-1.0.0.tgz","fileCount":59,"unpackedSize":178966,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCvctsL8/f0/RZAeRPcmUDmWDHgX0DzDbOyGJ04iHtOdwIhAM8B1PmbcI+zFNQN+Dz16vkZ08GvTurMZY6bMdc64NdF"}]},"_npmUser":{"name":"rotfeat","email":"wyx-sg@foxmail.com"},"directories":{},"maintainers":[{"name":"rotfeat","email":"wyx-sg@foxmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/3d-file-parsers_1.0.0_1774405918001_0.12039777280542863"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-25T02:31:57.787Z","1.0.0":"2026-03-25T02:31:58.173Z","modified":"2026-03-25T02:31:58.354Z"},"maintainers":[{"name":"rotfeat","email":"wyx-sg@foxmail.com"}],"description":"Lightweight, zero-dependency parsers for niche 3D file formats (M3D, X3D, IrrMesh, Terragen, PTS) that major libraries don't support. Returns raw typed arrays — works with Three.js, Babylon.js, or any WebGL framework.","homepage":"https://3d-tools.fabrapid.com","keywords":["3d","parser","m3d","x3d","irrmesh","irrlicht","terragen","pts","point-cloud","mesh","webgl","threejs","babylonjs","file-format","3d-converter","typed-array","browser","wasm"],"repository":{"type":"git","url":"git+https://github.com/ROTFEAT/3d-file-parsers.git"},"author":{"name":"FabRapid","email":"dev@fabrapid.com"},"bugs":{"url":"https://github.com/ROTFEAT/3d-file-parsers/issues"},"license":"MIT","readme":"# 3d-file-parsers\n\nLightweight, framework-agnostic parsers for niche 3D file formats that **Three.js, Babylon.js, and Assimp.js don't natively support**.\n\nAll parsers return raw `Float32Array` / `Uint32Array` data — plug them into any WebGL/WebGPU renderer with zero adapter code.\n\n> **Used in production** at [3D Tools by FabRapid](https://3d-tools.fabrapid.com) — a free, browser-based 3D file converter supporting 70+ input formats and 23 output formats with zero server uploads.\n\n## Supported Formats\n\n| Parser | Format | Extension | Description |\n|--------|--------|-----------|-------------|\n| `parseM3D` | [Model3D](https://gitlab.com/bztsrc/model3d) | `.m3d` | Binary mesh format with optional zlib compression. Supports int16/float32/float64 vertex precision and polygon meshes. |\n| `parseX3D` | [X3D](https://www.web3d.org/specifications/) | `.x3d` | XML-based 3D scene format (ISO standard). Handles `IndexedFaceSet`, `IndexedTriangleSet`, and `Box` primitives with material colors. |\n| `parseIrrMesh` | [Irrlicht Mesh](https://irrlicht.sourceforge.io/) | `.irrmesh` | XML mesh format from the Irrlicht Engine. Supports `standard`, `2tcoords`, and `tangents` vertex types. |\n| `parseTerragen` | [Terragen](https://planetside.co.uk/) | `.ter` | Binary heightmap terrain format. Automatically triangulates the elevation grid into a renderable mesh. |\n| `parsePTS` | [Leica PTS](https://en.wikipedia.org/wiki/Point_cloud) | `.pts` | ASCII point cloud format used by Leica laser scanners. Supports XYZ, XYZ+intensity, and XYZ+intensity+RGB columns. |\n\n## Why This Exists\n\nWhen building [3d-tools.fabrapid.com](https://3d-tools.fabrapid.com), we needed to support dozens of 3D formats in the browser. Most common formats (GLTF, OBJ, STL, FBX) are well-covered by Three.js loaders and Assimp WASM. But several formats — M3D, X3D, IrrMesh, Terragen, and PTS — had no JavaScript parser available, or the existing implementations were tightly coupled to a specific rendering engine.\n\nWe wrote these parsers from scratch based on the official format specifications, tested them against real-world files, and extracted them into this standalone package so others don't have to.\n\n**Design principles:**\n- **Zero framework dependency** — returns plain typed arrays, not Three.js objects\n- **Isomorphic** — works in browsers and Node.js (XML parsers accept a custom `DOMParser`)\n- **Tiny footprint** — only `fflate` (3KB gzipped) for M3D's zlib decompression; everything else is zero-dep\n- **TypeScript-first** — full type definitions with documented interfaces\n\n## Installation\n\n```bash\n# pnpm\npnpm add 3d-file-parsers\n\n# npm\nnpm install 3d-file-parsers\n\n# yarn\nyarn add 3d-file-parsers\n```\n\n## Quick Start\n\n### Import everything\n\n```ts\nimport { parseM3D, parseX3D, parseIrrMesh, parseTerragen, parsePTS } from '3d-file-parsers';\n```\n\n### Or import individual parsers (tree-shakeable)\n\n```ts\nimport { parseM3D } from '3d-file-parsers/m3d';\nimport { parseX3D } from '3d-file-parsers/x3d';\nimport { parseIrrMesh } from '3d-file-parsers/irrmesh';\nimport { parseTerragen } from '3d-file-parsers/terragen';\nimport { parsePTS } from '3d-file-parsers/pts';\n```\n\n## Usage\n\n### Parse M3D (Model3D)\n\n```ts\nimport { parseM3D } from '3d-file-parsers';\n\nconst response = await fetch('model.m3d');\nconst buffer = await response.arrayBuffer();\n\nconst { positions, normals, indices, vertexCount, faceCount } = parseM3D(buffer);\n\nconsole.log(`Vertices: ${vertexCount}, Faces: ${faceCount}`);\n// positions: Float32Array — flat xyz array (length = vertexCount * 3)\n// normals:   Float32Array | null — auto-computed face normals\n// indices:   Uint32Array — triangle indices\n```\n\n### Parse X3D\n\n```ts\nimport { parseX3D } from '3d-file-parsers';\n\nconst response = await fetch('scene.x3d');\nconst text = await response.text();\n\nconst { meshes } = parseX3D(text);\n\nfor (const mesh of meshes) {\n  console.log(`Mesh: ${mesh.indices.length / 3} triangles`);\n  // mesh.positions: Float32Array\n  // mesh.normals:   Float32Array | null\n  // mesh.indices:   Uint32Array\n  // mesh.color?:    [r, g, b] — diffuse material color (0-1)\n}\n```\n\n#### Node.js usage (X3D / IrrMesh)\n\nXML-based parsers need a `DOMParser`. In Node.js, pass one from `@xmldom/xmldom`:\n\n```ts\nimport { DOMParser } from '@xmldom/xmldom';\nimport { parseX3D } from '3d-file-parsers';\n\nconst { meshes } = parseX3D(xmlString, new DOMParser());\n```\n\n### Parse IrrMesh (Irrlicht)\n\n```ts\nimport { parseIrrMesh } from '3d-file-parsers';\n\nconst response = await fetch('model.irrmesh');\nconst text = await response.text();\n\nconst { buffers } = parseIrrMesh(text);\n\nfor (const buf of buffers) {\n  console.log(`Buffer: ${buf.vertexCount} vertices, ${buf.faceCount} faces`);\n  // buf.positions: Float32Array\n  // buf.normals:   Float32Array\n  // buf.indices:   Uint32Array\n}\n```\n\n### Parse Terragen Terrain\n\n```ts\nimport { parseTerragen } from '3d-file-parsers';\n\nconst response = await fetch('terrain.ter');\nconst buffer = await response.arrayBuffer();\n\nconst { positions, indices, normals, xpts, ypts } = parseTerragen(buffer);\n\nconsole.log(`Terrain grid: ${xpts} x ${ypts} (${xpts * ypts} vertices)`);\n// Automatically triangulated — ready to render as a mesh\n```\n\n### Parse PTS Point Cloud\n\n```ts\nimport { parsePTS } from '3d-file-parsers';\n\nconst response = await fetch('scan.pts');\nconst buffer = await response.arrayBuffer();\n\nconst { positions, colors, pointCount, hasColor } = parsePTS(buffer);\n\nconsole.log(`Points: ${pointCount}, Has color: ${hasColor}`);\n// positions: Float32Array — flat xyz (length = pointCount * 3)\n// colors:    Float32Array | null — flat rgb normalized to 0-1\n```\n\n## Using with Three.js\n\nThe parsers return raw typed arrays. Here's how to create Three.js geometry:\n\n```ts\nimport * as THREE from 'three';\nimport { parseM3D } from '3d-file-parsers';\n\nconst data = parseM3D(buffer);\nconst geometry = new THREE.BufferGeometry();\n\ngeometry.setAttribute('position', new THREE.Float32BufferAttribute(data.positions, 3));\n\nif (data.normals) {\n  geometry.setAttribute('normal', new THREE.Float32BufferAttribute(data.normals, 3));\n}\n\nif (data.indices.length > 0) {\n  geometry.setIndex(new THREE.BufferAttribute(data.indices, 1));\n}\n\nconst mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial());\nscene.add(mesh);\n```\n\n### Point cloud with Three.js\n\n```ts\nimport * as THREE from 'three';\nimport { parsePTS } from '3d-file-parsers';\n\nconst data = parsePTS(buffer);\nconst geometry = new THREE.BufferGeometry();\n\ngeometry.setAttribute('position', new THREE.Float32BufferAttribute(data.positions, 3));\n\nif (data.colors) {\n  geometry.setAttribute('color', new THREE.Float32BufferAttribute(data.colors, 3));\n}\n\nconst material = new THREE.PointsMaterial({\n  size: 0.01,\n  vertexColors: data.hasColor,\n});\n\nconst points = new THREE.Points(geometry, material);\nscene.add(points);\n```\n\n## Using with Babylon.js\n\n```ts\nimport * as BABYLON from '@babylonjs/core';\nimport { parseM3D } from '3d-file-parsers';\n\nconst data = parseM3D(buffer);\nconst mesh = new BABYLON.Mesh('model', scene);\nconst vertexData = new BABYLON.VertexData();\n\nvertexData.positions = Array.from(data.positions);\nvertexData.indices = Array.from(data.indices);\n\nif (data.normals) {\n  vertexData.normals = Array.from(data.normals);\n}\n\nvertexData.applyToMesh(mesh);\n```\n\n## Using with Raw WebGL\n\n```ts\nimport { parseM3D } from '3d-file-parsers';\n\nconst data = parseM3D(buffer);\n\nconst positionBuffer = gl.createBuffer();\ngl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\ngl.bufferData(gl.ARRAY_BUFFER, data.positions, gl.STATIC_DRAW);\n\nconst indexBuffer = gl.createBuffer();\ngl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);\ngl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data.indices, gl.STATIC_DRAW);\n\ngl.drawElements(gl.TRIANGLES, data.indices.length, gl.UNSIGNED_INT, 0);\n```\n\n## API Reference\n\n### `parseM3D(buffer: ArrayBuffer): M3DData`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `positions` | `Float32Array` | Flat xyz vertex positions |\n| `normals` | `Float32Array \\| null` | Auto-computed vertex normals |\n| `indices` | `Uint32Array` | Triangle indices |\n| `vertexCount` | `number` | Number of vertices |\n| `faceCount` | `number` | Number of triangles |\n\n### `parseX3D(xmlText: string, domParser?): X3DData`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `meshes` | `X3DMesh[]` | Array of parsed meshes |\n| `meshes[].positions` | `Float32Array` | Flat xyz vertex positions |\n| `meshes[].normals` | `Float32Array \\| null` | Computed vertex normals |\n| `meshes[].indices` | `Uint32Array` | Triangle indices |\n| `meshes[].color` | `[r, g, b]?` | Diffuse material color (0-1) |\n\n### `parseIrrMesh(xmlText: string, domParser?): IrrMeshData`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `buffers` | `IrrMeshBuffer[]` | Array of mesh buffers |\n| `buffers[].positions` | `Float32Array` | Flat xyz vertex positions |\n| `buffers[].normals` | `Float32Array` | Vertex normals from file |\n| `buffers[].indices` | `Uint32Array` | Triangle indices |\n| `buffers[].vertexCount` | `number` | Vertices in this buffer |\n| `buffers[].faceCount` | `number` | Triangles in this buffer |\n\n### `parseTerragen(buffer: ArrayBuffer): TerragenData`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `positions` | `Float32Array` | Flat xyz vertex positions |\n| `indices` | `Uint32Array` | Triangle indices (2 per grid quad) |\n| `normals` | `Float32Array` | Computed vertex normals |\n| `xpts` | `number` | Grid points along X axis |\n| `ypts` | `number` | Grid points along Y axis |\n\n### `parsePTS(buffer: ArrayBuffer): PTSData`\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `positions` | `Float32Array` | Flat xyz point positions |\n| `colors` | `Float32Array \\| null` | RGB colors normalized 0-1 (null if no color data) |\n| `pointCount` | `number` | Number of points |\n| `hasColor` | `boolean` | Whether the file contained color data |\n\n## Browser Support\n\nWorks in all modern browsers with `ArrayBuffer` and `DataView` support (Chrome 49+, Firefox 42+, Safari 10+, Edge 14+).\n\nFor Node.js, XML-based parsers (X3D, IrrMesh) require a DOM parser like [`@xmldom/xmldom`](https://www.npmjs.com/package/@xmldom/xmldom).\n\n## Related Projects\n\n- [3D Tools by FabRapid](https://3d-tools.fabrapid.com) — Free online 3D file converter (70+ formats, zero uploads, browser-only)\n- [3D File Viewer](https://3d-tools.fabrapid.com/viewer) — Online 3D model viewer with support for all major formats\n- [3D Model Compressor](https://3d-tools.fabrapid.com/compress) — Browser-based GLB compression with before/after comparison\n- [Assimp](https://github.com/assimp/assimp) — The industry-standard C++ import library (covers most common formats)\n- [Three.js](https://github.com/mrdoob/three.js) — WebGL rendering library with many built-in loaders\n- [fflate](https://github.com/101arrowz/fflate) — Fast JavaScript compression library (used for M3D zlib decompression)\n\n## Contributing\n\nContributions are welcome! If you need support for additional niche 3D formats, please [open an issue](https://github.com/ROTFEAT/3d-file-parsers/issues).\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-a96746d84d7ed204e476edacf96f442a"}