πŸ” ⌘K
Introduction

StlTo3mf Technical Overview

StlTo3mf is a high-performance, 100% memory-safe STL-to-3MF conversion and mesh healing pipeline written in pure Rust (enforcing #![forbid(unsafe_code)]). Powered by the Omni3MF geometry engine, it bridges legacy CAD mesh output with modern additive manufacturing slicers.

πŸ›‘οΈ

100% Safe Rust

Zero unsafe blocks across the entire workspace. Guaranteed spatial memory safety, thread safety, and crash-free execution.

⚑

Deterministic & Fast

Rayon multi-threaded CLI processing thousands of triangles per millisecond, alongside an in-browser WebAssembly and pure client-side engine.

🧩

Multi-Shell Separation

Disjoint Set Union (DSU) topological clustering splits compound STLs into discrete, colorable 3MF <object> nodes.

🧹

Profile Sanitization

Purges unverified vendor printer profiles, temperature overrides, and hidden G-code scripts while preserving filament colors.

πŸ’‘
Zero Server Dependencies: StlTo3mf runs both as an ultra-fast compiled native CLI and as a zero-backend client-side web application. All geometric repair, shell separation, and 3MF packaging happen directly on your machine or inside your browser tab without any telemetry or file uploads.

30-Second Quickstart

Option A: Instant Browser Studio (Zero Install)

No build tools or installation needed. Simply open the Web Studio directly in your web browser:

  1. Click Launch Web Studio or navigate to the converter root.
  2. Drag & drop any ASCII or binary .stl model into the drop zone.
  3. Inspect the interactive 3D WebGL preview and click ⚑ Convert & Download 3MF.

Option B: High-Throughput Native CLI

Compile the optimized native Rust binary using Cargo:

bash
# Clone repository and build optimized release binary
git clone https://github.com/madireis/stl-to-3mf.git
cd stl-to-3mf
cargo build --release --bin stl-to-3mf

# Convert single STL with auto-repair, shell splitting, and profile sanitization
./target/release/stl-to-3mf convert model.stl -o model.3mf --strip-slicer-config

# Batch convert an entire directory in parallel using Rayon
./target/release/stl-to-3mf convert ./models/ -o ./output_3mf/ --threads 0
Format Comparison

Why Migrate from STL to 3MF?

Created in 1987, the STL (Standard Triangle Language) format was designed for rudimentary stereolithography. Modern 3D printing requires multi-material identification, unit scaling, watertight validation, and thumbnail metadata. Here is how StlTo3mf elevates your files:

Feature / Characteristic Legacy STL Format Modern 3MF (StlTo3mf Engineered)
Data Container Raw uncompressed float list (binary or ASCII) OPC ZIP container with XML schemas & Deflate compression
Multi-Body / Multi-Shell ❌ Impossible; all bodies fused into single triangle cloud βœ… Discrete <object> nodes with independent IDs and colors
Dimensional Units ❌ Undefined; slicer guesses millimeters or inches βœ… Explicit unit="millimeter" declared in root XML schema
Color & Filament Materials ❌ None in standard specification βœ… Native <m:colorgroup> palette with hex RGBA mapping
Topology & Watertightness ⚠️ Frequently riddled with duplicate vertices and open holes βœ… Automated 11-stage spatial welding and boundary loop patching
File Size & Bandwidth ❌ Heavy; 50 bytes per triangle, zero compression βœ… Lightweight; 60%–80% smaller thanks to vertex indexing and ZIP
Slicer & Printer Previews ❌ Requires slow offline parsing of millions of vertices βœ… Embedded 256Γ—256 PNG thumbnail at /Metadata/thumbnail.png
Slicer Security N/A βœ… Sanitizer scrubs third-party printer overrides & custom G-code
CLI Reference

CLI Commands & Parameter Reference

The StlTo3mf command-line tool provides three subcommands: convert, inspect, and sanitize. The binary can be invoked using any of its compiled aliases: stl-to-3mf, stls-to-3mf, or omni3mf.

Subcommand: convert

Converts single STL files or entire directories into compliant 3MF packages with full mesh repair and shell splitting.

bash
stl-to-3mf convert <INPUT> [OPTIONS]
Flag / Option Type Default Description
<INPUT> Path (Required) Path to single .stl file or directory of STLs.
-o, --output <PATH> Path <input>.3mf Target output file path or target directory for batch jobs.
--merge-tolerance <f64> Float 1e-6 Spatial welding radius in millimeters for coincident vertices.
--no-repair Flag false Disables boundary hole loop extraction and ear-clipping hole patching.
--hole-max-edges <usize> Integer 64 Maximum perimeter edges in a single boundary loop permitted for auto-patching.
--no-split Flag false Preserves all faces as one object; bypasses DSU shell separation.
--strip-slicer-config Flag false Purges embedded slicer presets, acceleration profiles, and custom G-code.
--preserve-supports Bool true Retains slicer-generated support structure meshes if present.
--scale <f64> Float 1.0 Uniform scale multiplier (e.g. 25.4 converts inches to mm).
--threads <usize> Integer 0 Rayon worker thread count. 0 uses all logical CPU cores.
-q, --quiet Flag false Mutes terminal progress bars, spinners, and informative output.
-v, --verbose Flag false Enables diagnostic debug logging of vertices, loops, and packaging.

Subcommand: inspect

Analyzes an STL or 3MF model's topology, dimensions, watertightness, and scale sanity without modifying the file.

bash
# Human-readable diagnostic output
stl-to-3mf inspect complex_bracket.stl

# Structured JSON output for CI/CD and pre-flight pipelines
stl-to-3mf inspect complex_bracket.stl --json

Example JSON diagnostics schema returned by --json:

json
{
  "format": "binary",
  "raw_triangles": 48200,
  "deduplicated_vertices": 24102,
  "degenerate_facets_pruned": 14,
  "boundary_holes_detected": 2,
  "shells_count": 3,
  "is_watertight": true,
  "bounding_box": {
    "min": [-45.0, -22.5, 0.0],
    "max": [45.0, 22.5, 35.8],
    "dimensions": [90.0, 45.0, 35.8]
  },
  "scale_sanity": {
    "status": "normal",
    "suggested_multiplier": 1.0
  }
}

Subcommand: sanitize

Cleans an existing .3mf package downloaded from the web, stripping unsafe printer configuration overrides while maintaining geometry, colors, and components.

bash
stl-to-3mf sanitize untrusted_download.3mf -o safe_clean.3mf
Automation

Real-World Recipes & Batch Scripts

Common production command patterns for print farm automation, 3D scan healing, and CI/CD validation.

Recipe 1: Multi-Color Shell Separation for Bambu Studio & OrcaSlicer

Ensure disconnected pieces (e.g. eyes, buttons, body parts) become independent objects ready for filament assignment:

bash
stl-to-3mf convert character_multicolor.stl -o character.3mf \
  --merge-tolerance 1e-6 \
  --strip-slicer-config

Recipe 2: Aggressive Hole Healing for Defective 3D Scans

Increase boundary perimeter tolerance to patch larger scanning holes and force normal alignment:

bash
stl-to-3mf convert raw_scan.stl -o healed_scan.3mf \
  --hole-max-edges 256 \
  --merge-tolerance 1e-5 \
  --verbose

Recipe 3: Parallel Batch Directory Processing (PowerShell)

Convert all STL files in a folder into individual 3MF packages in Windows PowerShell:

powershell
Get-ChildItem -Path .\stls\ -Filter *.stl | ForEach-Object {
    $outPath = Join-Path .\3mf_output\ ($_.BaseName + ".3mf")
    stl-to-3mf convert $_.FullName -o $outPath --strip-slicer-config
}

Recipe 4: CI/CD Mesh Validation Gate (Bash + jq)

Verify that all generated mechanical parts in your repository are strictly watertight before merging pull requests:

bash
for f in cad_exports/*.stl; do
  IS_WATERTIGHT=$(stl-to-3mf inspect "$f" --json | jq -r '.is_watertight')
  if [ "$IS_WATERTIGHT" != "true" ]; then
    echo "❌ Validation Failure: $f is NOT watertight!"
    exit 1
  fi
done
echo "βœ… All CAD meshes verified 100% watertight."
Web Integration

Web Studio & REST API Guide

StlTo3mf includes a sleek web application running either 100% client-side in static hosting environments or via an isolated Node.js HTTP server.

Starting the Local Server

The local HTTP service in web/server.js requires zero external npm dependenciesβ€”it relies purely on standard Node.js modules (http, fs, path, child_process):

bash
# Run with default port 3000
node web/server.js

# Run with custom port
PORT=8080 node web/server.js

REST API Reference

Endpoint Method Content-Type Description
/ GET text/html Serves the Web Studio 3D conversion frontend.
/docs/ GET text/html Serves this documentation portal.
/api/convert POST multipart/form-data Uploads an STL and streams back the generated .3mf binary package.
/api/inspect POST multipart/form-data Returns diagnostic JSON (watertightness, volume, shell count, bounds).

POST /api/convert

Accepts a multipart form with an STL file and parameters, returning a freshly packaged .3mf binary archive.

Example curl API Request:

bash
curl -X POST http://localhost:3000/api/convert \
  -F "file=@sample_gear.stl" \
  -F "split_shells=true" \
  -F "repair=true" \
  -F "strip_slicer_config=true" \
  -o sample_gear.3mf
Zero-Backend

Client-Side Geometry Engine (Browser Runtime)

When hosted statically on GitHub Pages or Cloudflare Pages, StlTo3mf converts and heals models directly in JavaScript without sending a single byte to an external server.

The client-side engine consists of five coordinated ES6 modules located in web/public/assets/js/:

  • stl-parser.js: Ingests binary STL buffers via DataView and ASCII STLs using regex tokenizers directly into continuous Float32Array position buffers.
  • mesh-repair.js: Implements spatial hash grid vertex welding ($10^{-6}\text{ mm}$ cell size), degenerate facet elimination, boundary loop edge extraction, and Gauss Divergence signed volume checks.
  • shell-separator.js: Implements Disjoint Set Union (DSU) to group triangles sharing undirected edges into distinct shells with compact 0-based vertex re-indexing.
  • viewer3d.js: Three.js WebGL viewport featuring OrbitControls, independent multi-color shell rendering, glowing red boundary hole wireframe highlights, and offscreen 256Γ—256 thumbnail capture.
  • threemf-packager.js: Builds compliant OPC ZIP packages entirely in memory using fflate, generating [Content_Types].xml, _rels/.rels, and 3D/3dmodel.model.
Architecture

The 11-Stage Geometry Repair Pipeline

Every mesh processed by StlTo3mf passes through an 11-stage pipeline designed to eliminate non-manifold geometry, ensure positive signed volume, and package compliant 3MF archives.

1

Format Detection & Ingestion

Determines binary vs ASCII STL. Valid binary files follow $L = 84 + 50 \times N$ bytes. ASCII files are parsed via streaming tokenizers supporting scientific float notations.

2

Numeric Sanitization & Guarding

Tests all $(x, y, z)$ coordinates against f64::NAN and $\pm\infty$. Flushes subnormal floats to prevent CPU denormal execution penalties.

3

Spatial Hash Grid Vertex Welding

Raw STLs store 3 independent vertices per triangle. StlTo3mf hashes coordinates into cubic cells of width $\delta = 10^{-6}\text{ mm}$. A 27-neighborhood stencil query collapses coincident points into an indexed representation in $O(N)$ expected time.

4

Degenerate Triangle Pruning

Removes collapsed triangles (duplicate vertex indices) and collinear slivers where cross-product area $\|(\mathbf{v}_1 - \mathbf{v}_0) \times (\mathbf{v}_2 - \mathbf{v}_0)\|^2 < 10^{-24}\text{ mm}^4$.

5

Directed Edge Adjacency & Boundary Loop Detection

Indexes directed edges $u \to v$. Edges lacking an opposite twin $v \to u$ are marked as boundary edges and assembled into closed topological cycles.

6

Topological BFS Winding Propagation

Starting from an arbitrary seed facet, walks adjacent shared edges via BFS. If an adjacent facet shares an edge with identical orientation rather than reversed, its vertex indices are swapped ($v_1 \leftrightarrow v_2$).

7

Outward Normal Rectification via Divergence Theorem

Evaluates polyhedral signed volume $V(\Omega) = \frac{1}{6} \sum \mathbf{p}_0 \cdot (\mathbf{p}_1 \times \mathbf{p}_2)$. If $V < 0$, the shell is wound inside out and all facets are inverted to point outward.

8

Newell Projection & Ear-Clipping Hole Healing

Calculates the best-fit 3D plane normal for each boundary loop using Newell's method, projects onto the dominant 2D axis plane, and clips convex ears to patch holes with valid planar triangles.

9

Dual Face Graph & DSU Shell Splitting

Constructs a dual graph of faces connected by shared undirected edges. Uses Disjoint Set Union with path compression to partition disconnected shells with 0-based re-indexing.

10

Dynamic Scale Sanity Evaluation

Analyzes bounding box dimensions against physical 3D print volumes. Flags anomalies under $2\text{ mm}$ (likely inches or meters) or over $5000\text{ mm}$ (microns or centimeters).

11

Thumbnail Rasterization & OPC ZIP Packaging

Renders an orthographic $256 \times 256$ RGBA thumbnail with Lambertian diffuse shading, builds 3MF XML documents, and writes a Deflate-compressed PKZIP archive.

Mathematics

Mathematical Proofs & Derivations

Rigorous mathematical foundations underpinning StlTo3mf's geometry engine.

1. Gauss-Ostrogradsky Divergence Theorem for Signed Volume

Theorem: Let $\Omega \subset \mathbb{R}^3$ be a compact, orientable 3-manifold with piecewise smooth boundary $\partial \Omega$. For any continuously differentiable vector field $\mathbf{F}: \Omega \to \mathbb{R}^3$:

Divergence Theorem
∭_Ξ© (βˆ‡ Β· F) dV = ∬_βˆ‚Ξ© (F Β· n) dS

Choose the linear position vector field $\mathbf{F}(\mathbf{x}) = \frac{1}{3}\mathbf{x} = \frac{1}{3}(x\hat{\mathbf{i}} + y\hat{\mathbf{j}} + z\hat{\mathbf{k}})$. The divergence is constantly 1:

βˆ‡ Β· F = 1/3 ( βˆ‚x/βˆ‚x + βˆ‚y/βˆ‚y + βˆ‚z/βˆ‚z ) = 1/3 (1 + 1 + 1) = 1

Substituting into the volume integral:

V(Ξ©) = ∭_Ξ© 1 dV = 1/3 ∬_βˆ‚Ξ© (x Β· n) dS

For a closed surface discretized into planar triangular facets $f_i = (\mathbf{p}_0, \mathbf{p}_1, \mathbf{p}_2)$, evaluating the surface integral yields the exact summation:

Exact Polyhedral Signed Volume
V(Ξ©) = 1/6 βˆ‘_{i=1}^{F} p_{0, i} Β· (p_{1, i} Γ— p_{2, i})

Decision Criterion: If $V(\Omega) > 0$, the surface facets are consistently wound counter-clockwise when viewed from the outside (normals point outward). If $V(\Omega) < 0$, the shell is inverted; StlTo3mf swaps vertices $\mathbf{p}_1 \leftrightarrow \mathbf{p}_2$ on all faces.

2. Newell's Method for 3D Polygon Normal Estimation

Boundary loops $[v_0, v_1, \dots, v_{k-1}]$ extracted from 3D meshes are often non-planar. Simple cross products of two edges fail when edges are collinear or noisy. Newell's algorithm calculates the exact projected area integrals along all three cardinal planes:

Newell Normal Components
N_x = βˆ‘_{i=0}^{k-1} (y_i - y_{i+1})(z_i + z_{i+1})
N_y = βˆ‘_{i=0}^{k-1} (z_i - z_{i+1})(x_i + x_{i+1})
N_z = βˆ‘_{i=0}^{k-1} (x_i - x_{i+1})(y_i + y_{i+1})

where index $k \equiv 0$ (cyclic loop). The unit normal is obtained by $\hat{\mathbf{n}} = \mathbf{N} / \|\mathbf{N}\|$. StlTo3mf projects the loop into 2D by dropping the axis with $\max(|n_x|, |n_y|, |n_z|)$, preventing coordinate distortion before ear-clipping.

3. Ear-Clipping Triangulation with Barycentric Containment

A vertex $w_i$ in a projected 2D polygon $P$ forms a clippable "ear" if it is strictly convex ($\det > 0$) and no other polygon vertex $w_j$ lies within the triangle $\Delta(w_{i-1}, w_i, w_{i+1})$. Point containment is verified using barycentric coordinates $(\lambda_1, \lambda_2, \lambda_3)$:

Barycentric Coordinates
Ξ»_1 β‰₯ 0, Ξ»_2 β‰₯ 0, Ξ»_3 β‰₯ 0, Ξ»_1 + Ξ»_2 + Ξ»_3 = 1
Packaging

3MF Open Packaging Conventions (OPC) Specification

A valid 3MF file is an Open Packaging Conventions (OPC) PKZIP archive conforming to the 3MF Core Specification v1.x.

tree
model.3mf (Deflate ZIP Archive)
β”œβ”€β”€ [Content_Types].xml         # Declares MIME content types
β”œβ”€β”€ _rels/
β”‚   └── .rels                   # Root relationships linking model & thumbnail
β”œβ”€β”€ 3D/
β”‚   β”œβ”€β”€ 3dmodel.model           # 3MF geometric model XML ( & )
β”‚   └── _rels/
β”‚       └── 3dmodel.model.rels  # Thumbnail metadata relationship
└── Metadata/
    └── thumbnail.png           # 256x256 RGBA preview thumbnail

Multi-Shell 3D/3dmodel.model Architecture

When multi-shell separation is enabled, each disjoint component is serialized as an independent <object> element with its own unique ID and coordinate buffer:

xml
<?xml version="1.0" encoding="UTF-8"?>
<model unit="millimeter" xml:lang="en-US"
       xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02"
       xmlns:m="http://schemas.microsoft.com/3dmanufacturing/material/2015/02">
  <metadata name="Title">StlTo3mf Multi-Shell Export</metadata>
  <metadata name="Application">StlTo3mf (Omni3MF Engine)</metadata>

  <resources>
    <!-- Color Palette Definition -->
    <m:colorgroup id="1">
      <m:color color="#38BDF8FF" />
      <m:color color="#F97316FF" />
    </m:colorgroup>

    <!-- Object 1: Body Shell -->
    <object id="2" name="Shell_1" type="model" pid="1" pindex="0">
      <mesh>
        <vertices> ... </vertices>
        <triangles> ... </triangles>
      </mesh>
    </object>

    <!-- Object 2: Detail Shell -->
    <object id="3" name="Shell_2" type="model" pid="1" pindex="1">
      <mesh>
        <vertices> ... </vertices>
        <triangles> ... </triangles>
      </mesh>
    </object>
  </resources>

  <build>
    <item objectid="2" />
    <item objectid="3" />
  </build>
</model>
Compatibility

Slicer Compatibility Matrix

StlTo3mf packages are tested and verified across all major commercial and open-source slicers used in consumer and industrial additive manufacturing.

Slicer Software Verified Versions Multi-Shell Splitting Sanitizer Protection Thumbnail Display Overall Status
Bambu Studio v1.8, v1.9, v2.0+ βœ… Native Multi-Part Dialog βœ… Strips dangerous configs βœ… Renders on LCD & GUI βœ“ 100% Verified
OrcaSlicer v1.9, v2.0, v2.1+ βœ… Discrete Per-Object Control βœ… Preserves custom filaments βœ… Full 256x256 display βœ“ 100% Verified
PrusaSlicer v2.6, v2.7, v2.8+ βœ… Multi-Object Hierarchy βœ… Drops vendor presets βœ… Plate preview thumbnail βœ“ 100% Verified
UltiMaker Cura v5.2, v5.6+ βœ… Multi-Component Grouping βœ… Neutral parameters βœ… Cura project preview βœ“ 100% Verified
SuperSlicer v2.4, v2.5+ βœ… Independent Parts List βœ… Clean baseline config βœ… Viewport preview βœ“ 100% Verified

Bambu Studio & OrcaSlicer Workflow

  1. Open Bambu Studio or OrcaSlicer.
  2. Drag your converted .3mf file directly onto the build plate.
  3. When prompted: "Load these objects as a single multi-part object?", select Yes.
  4. Each separated shell appears in the left object list, allowing 1-click filament / AMS color assignment.
Quality Assurance

Contributing & Synthetic Test Suite

StlTo3mf maintains rigorous quality assurance through a programmatic 85-test synthetic verification suite, guaranteeing stability against pathological geometry.

⚠️
The Zero-Unsafe Invariant: Every Rust crate in this workspace strictly forbids unsafe code via #![forbid(unsafe_code)]. PRs containing unsafe blocks or disabling this flag will fail automated review gates.

Why Programmatic Synthetic Testing?

To maintain a lightweight git history without checking multi-megabyte binary STL files into the repository, all test meshes are mathematically generated in Rust:

  • Canonical Cubes: 12 triangles forming watertight 2-manifold closed boundaries.
  • Deliberate Holes: Cubes with dropped faces verifying boundary edge cycle extraction and ear-clipping hole patches.
  • Degenerate Facets: Collinear zero-area triangles and duplicate vertices verifying sub-micron spatial hash welding.
  • Compound Shells: Multiple separated shapes testing DSU graph clustering and 0-based re-indexing.

Running Verification Gates

Before submitting any pull request, ensure all test gates pass cleanly:

bash
# 1. Check code formatting
cargo fmt --all -- --check

# 2. Enforce zero compiler & clippy warnings
cargo clippy --workspace --all-targets -- -D warnings

# 3. Execute all 85 workspace synthetic and invariant tests
cargo test --workspace

# 4. Execute client-side web engine verification suite
node test/client_engine_test.js