This document is just my notes from our meetup discussion/exploration of 3mf files.
The 3mf core specification is available at https://3mf.io/spec/
Here are some important excerpts.
Section 1.1: 3mf files are zip files. This means that if you change the filename from dot 3mf to dot zip and then you can unzip them using your normal zip tools.
Section 2 of the specification describes the parts inside the package. 3mf files follow Open Packaging Conventions
https://en.wikipedia.org/wiki/Open_Packaging_Conventions
A 3mf file contains a PAYLOAD. A payload is a complete set of interdependent parts in a package. If the root part of the payload is a 3d model then it is a 3d payload. There can be more than one 3d payload in a 3mf file but only one 3d payload can be the primary 3d payload. The primary 3d payload is defined in the 3MF Document StartPart. Here’s a list of 3MF parts. Note that this is not a complete list because the 3MF format is extensible to include custom parts.
Name |
Description |
Relationship Source |
Required/Optional |
---|---|---|---|
3D Model |
Contains the description of one or more 3D objects for manufacturing. |
Package |
REQUIRED |
Core Properties |
The OPC part that contains various document properties. |
Package |
OPTIONAL |
Digital Signature Origin |
The OPC part that is the root of digital signatures in the package. |
Package |
OPTIONAL |
Digital Signature |
OPC parts that each contains a digital signature. |
Digital Signature Origin |
OPTIONAL |
Digital Signature Certificate |
OPC parts that contain a digital signature certificate. |
Digital Signature |
OPTIONAL |
PrintTicket |
Provides settings to be used when outputting the 3D object(s) in the 3D Model part. |
3D Model |
OPTIONAL |
Package Thumbnail |
Contains a small JPEG or PNG image that represents the 3D objects in the package or the package as a whole. |
Package |
OPTIONAL |
Object Thumbnail |
Contains a small JPEG or PNG image that represents a 3D object in a 3D Model. |
3D Model |
OPTIONAL |
3D Texture |
Contains a texture used to apply color to a 3D object in the 3D Model part (available for extensions) |
3D Model |
OPTIONAL |
Custom Parts |
OPC parts that are associated with metadata |
Package |
OPTIONAL |
Ok enough theory. Suppose I create a cube in freecad with one corner at (0,0,0) and the opposite corner at (10,10,10) and export the cube as a 3mf file. This is what I see when I unzip the file:
├── 3D │ └── 3dmodel.model ├── [Content_Types].xml ├── Metadata │ └── thumbnail.png └── _rels
In the root folder there’s an xml file named [Content_Types].xml and three subfolders: 3D, Metadata and _rels. Here’s the contents of the xml file and the thumbnail.png file
<?xml version='1.0' encoding='UTF-8'?> <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Default Extension="model" ContentType="application/vnd.ms-package.3dmanufacturing-3dmodel+xml"/> <Default Extension="png" ContentType="image/png"/> </Types>
And this is the 3dmodel.model file:
<?xml version="1.0" encoding="UTF-8"?> <model unit="millimeter" xml:lang="en-US" xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02"> <metadata name="Application">FreeCAD</metadata> <resources> <object id="1" type="model"> <mesh> <vertices> <vertex x="0" y="0" z="0" /> <vertex x="0" y="0" z="10" /> <vertex x="0" y="10" z="0" /> <vertex x="0" y="10" z="10" /> <vertex x="10" y="0" z="10" /> <vertex x="10" y="0" z="0" /> <vertex x="10" y="10" z="0" /> <vertex x="10" y="10" z="10" /> </vertices> <triangles> <triangle v1="0" v2="1" v3="2" /> <triangle v1="2" v2="1" v3="3" /> <triangle v1="4" v2="5" v3="6" /> <triangle v1="4" v2="6" v3="7" /> <triangle v1="5" v2="4" v3="0" /> <triangle v1="0" v2="4" v3="1" /> <triangle v1="7" v2="6" v3="2" /> <triangle v1="7" v2="2" v3="3" /> <triangle v1="2" v2="6" v3="0" /> <triangle v1="0" v2="6" v3="5" /> <triangle v1="7" v2="3" v3="1" /> <triangle v1="7" v2="1" v3="4" /> </triangles> </mesh> </object> </resources> <build> <item objectid="1" transform="1 0 0 0 1 0 0 0 1 0 0 0" /> </build> </model>
This looks familiar: it’s a triangular mesh similar to STL but slightly upgraded. That is to say, the vertices are specified first using a list then the triangles references the list of vertices. Which is great because this technique reduces the risk of non-aligned edges due to round off errors. There’s some metadata to tell us what application created the model, the units, and a transformation matrix at the end if we want to scale or rotate the object.
As an example of a more complex object we could look at an export of a Bambu Studio sliced file.
Suppose I open my freecad cube.3mf file in Bambu Studio. Slice it. But instead of printing it, use the drop down, select Export All and export it as cube.gcode.3mf. By default Bambu Studio exports its gcode as 3mf files (you can select bare gcode export in File→Export menu). Here’s what I get when I unzip the cube.gcode.3mf file:
├── 3D │ └── 3dmodel.model ├── [Content_Types].xml ├── Metadata │ ├── cut_information.xml │ ├── model_settings.config │ ├── pick_1.png │ ├── plate_1.gcode │ ├── plate_1.gcode.md5 │ ├── plate_1.json │ ├── plate_1.png │ ├── plate_1_small.png │ ├── plate_no_light_1.png │ ├── project_settings.config │ ├── _rels │ │ └── model_settings.config.rels │ ├── slice_info.config │ └── top_1.png └── _rels
and this is [Content_Types].xml
<?xml version="1.0" encoding="UTF-8"?> <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Default Extension="model" ContentType="application/vnd.ms-package.3dmanufacturing-3dmodel+xml"/> <Default Extension="png" ContentType="image/png"/> <Default Extension="gcode" ContentType="text/x.gcode"/> </Types>
and here’s the 3dmodel.model file
<?xml version="1.0" encoding="UTF-8"?> <model unit="millimeter" xml:lang="en-US" xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02" xmlns:BambuStudio="http://schemas.bambulab.com/package/2021" xmlns:p="http://schemas.microsoft.com/3dmanufacturing/production/2015/06" requiredextensions="p"> <metadata name="Application">BambuStudio-02.00.01.50</metadata> <metadata name="BambuStudio:3mfVersion">1</metadata> <metadata name="Copyright"></metadata> <metadata name="CreationDate">2025-06-12</metadata> <metadata name="Description"></metadata> <metadata name="Designer"></metadata> <metadata name="DesignerCover"></metadata> <metadata name="DesignerUserId">2876920761</metadata> <metadata name="License"></metadata> <metadata name="ModificationDate">2025-06-12</metadata> <metadata name="Origin"></metadata> <metadata name="Title"></metadata> <resources> </resources> <build/> </model>
Interestingly, it’s all just metadata. There’s no object. And if we try to open this cube.gcode.3mf file in Bambu Studio it will show a sliced model in the Preview tab but it will complain when we try to switch to the Prepare tab because there is no object. Does it still count as a 3d payload even if there is no 3d object in the model? Maybe Bambu is being sneaky with the standard.
We have lots of files in the Metadata folder, including files describing the model and printer settings (in xml and json respectively). And of course the actual gcode that we are looking for is in the Metadata folder.