Bambu/Orca .3mf 檔案實際包含甚麼?
What’s actually inside a Bambu/Orca .3mf
Bambu Studio 和 OrcaSlicer 的 .3mf 專案檔除了網格資料,還包含重建切片專案所需的設定、物件關係和擺放資訊。這類檔案是 ZIP 封存檔,設定檔分別記錄專案層級設定、物件與零件設定,以及切片結果。要還原場景,必須從根模型追蹤物件引用並套用各層變換;只讀取封存檔內的網格,無法重建完整場景。
A painted model can open in another application with the right shape and the wrong colors. A project with several build plates can turn into one sprawling scene. Sometimes the preview is empty even though the archive contains plenty of mesh data.
Those failures often come from reading only one layer of the file.
Bambu Studio and OrcaSlicer save geometry alongside the settings and relationships that make it a slicer project. The mesh tells you where the surfaces are. Other entries tell you which filament a part uses, how its surface was painted, and which copy belongs on which plate.
To reconstruct the project, those records have to stay connected.
The examples below use shortened fragments and illustrative IDs. They describe the shared Bambu/Orca project structure; the exact contents vary with the slicer version and export type.
1. A .3mf is a ZIP archive
You can inspect a .3mf with an ordinary ZIP tool:
unzip -l project.3mf
There is no need to rename it first.
Underneath, 3MF uses Open Packaging Conventions. XML relationship files connect the package’s parts, and [Content_Types].xml identifies their content types. The package-level relationship file, _rels/.rels, identifies the root 3D model. In a typical Bambu/Orca project, that model is 3D/3dmodel.model. The relationship is the formal entry point; the familiar filename is a convention. 3MF Core Specification
A representative archive might contain:
[Content_Types].xml
_rels/
.rels
3D/
3dmodel.model
_rels/
3dmodel.model.rels
Objects/
object_1.model
object_2.model
Metadata/
project_settings.config
model_settings.config
slice_info.config
plate_1.png
plate_1.json
plate_1.gcode
This is an example, not a required inventory. An unsliced project and an exported print job can contain different subsets.
The three configuration files answer different questions:
| Entry | Format | What it describes |
|---|---|---|
Metadata/project_settings.config |
JSON | Project-wide printer, process, and filament settings |
Metadata/model_settings.config |
XML | Object and part settings, plate definitions, and instance membership |
Metadata/slice_info.config |
XML | Saved results for sliced plates, including time and filament usage |
These paths are explicitly defined in the slicers’ archive implementation. The .config suffix does not identify a common serialization format. OrcaSlicer’s 3MF implementation
project_settings.config contains settings such as layer height and the project’s filament palette. A shortened example looks like this:
{
"layer_height": "0.2",
"filament_colour": ["#FFFFFF", "#D32F2F"],
"filament_type": ["PLA", "PLA"]
}
The spelling filament_colour is the actual key.
Notice that the layer height is a string. The slicer’s JSON serializer writes many configuration values as strings and vector options as arrays of serialized strings. A reader should interpret each option according to its meaning instead of assuming that every numeric setting arrives as a JSON number. OrcaSlicer’s configuration serializer
For an inspector or asset browser, this suggests a useful starting point: read the small configuration entries before decoding the meshes. You can discover much of the project’s structure without loading millions of triangles.
2. Production Extension connects the root model to other model files
Opening 3D/3dmodel.model does not guarantee that you will find vertices there.
The root can contain assembly objects whose components reference meshes in other .model entries. A component might look like this:
<component
p:path="/3D/Objects/object_1.model"
objectid="1"
transform="1 0 0 0 1 0 0 0 1 10 0 0"/>
Here, p:path identifies a model file inside the ZIP. It is absolute within the package, not an operating-system path. objectid="1" selects an object in that file. The Production Extension permits a referenced object to contain components of its own. 3MF Production Extension
That gives the reader a chain to follow:
Figure 1. The component points to another model entry inside the same ZIP. A referenced object can itself contain local components.
There is a precise distinction here. Component hierarchies can nest, but the published Production Extension restricts external p:path attributes on components to the root model. Components in a referenced model must refer to objects in that same model file. Arbitrary chains of external references across several files are outside that rule.
A recursive component resolver is still necessary. Recursion through assemblies and recursion across package files are different operations.
Object identity also needs its file context. A practical lookup key is:
(model entry path, object ID)
Using a bare integer risks confusing objects defined in different model files. Orca’s importer retains the model path alongside the referenced object ID, while its exporter writes each component’s volume transform. OrcaSlicer’s component import and export code
Transforms accumulate as the reader follows the hierarchy. The example above translates its referenced object by 10 units along X. The root build item can add another transform, and nested components can add more.
For application code using column vectors, the composition is:
world vertex =
build transform
× outer component transform
× inner component transform
× mesh vertex
3MF serializes an affine transform as 12 numbers, with the translation in the final three positions. Its serialized layout needs to be converted correctly for the matrix conventions of the rendering library. The model’s declared unit also matters. 3MF matrix and coordinate definitions
A useful test case is a translated parent containing a rotated child. Identity transforms hide multiplication-order mistakes.
Keep mesh resources separate from placed instances as well. Two instances can share the same mesh and appear at different positions. Parsing that mesh once is sensible; applying one placement to every copy is not.
The reconstruction should therefore start at the root build items and follow their references. Collecting every mesh in the ZIP produces an inventory of resources. It does not, by itself, reconstruct the scene.
3. paint_color belongs to triangle surfaces
The name makes paint_color sound simpler than it is.
In Bambu/Orca model XML, it appears on individual triangles:
<triangle
v1="0"
v2="1"
v3="2"
paint_color="4"/>
The attribute contains encoded painting data. It does not contain an RGB color.
Orca’s facet serialization uses "4" for a whole triangle painted with project filament 1, "8" for filament 2, and "0C" for filament 3. Reading "4" as “filament 4” already gives the wrong result. OrcaSlicer’s facet encoding
The painting system can also recursively subdivide an original mesh triangle. Its serialized data records the subdivision structure and the paint states of the resulting regions. One XML <triangle> can therefore contain several filament assignments. TriangleSelector definitions
That is how a painted boundary can cross the interior of a relatively large source triangle.
The encoded string is a hexadecimal representation of the subdivision data. The decoder reconstructs a tree containing split instructions and leaf states. A faithful preview must recover the painted subregions, including their boundaries. TriangleSelector serialization
Assigning one dominant filament to the original triangle is a preview approximation. It can make small painted details disappear or move a color boundary to an existing mesh edge. Such an approximation may be acceptable for a small thumbnail, but it should not be mistaken for a complete decoding of the saved paint.
Figure 2. Schematic painted subregions inside one source triangle. Keeping only its dominant state removes the smaller light region. This illustration is not a decoding of a specific paint_color string.
Unpainted regions have their own meaning. Paint state zero leaves the region to inherit its base filament assignment.
For an ordinary printable part, resolve the assignment in this order:
- Use the painted filament when the region has a nonzero paint state.
- Otherwise, use the part’s explicit filament assignment.
- If the part assignment is missing or zero, inherit the object’s assignment.
Bambu Studio’s ModelVolume::extruder_id() implements that part-to-object fallback. If the object assignment is absent too, that resolver defaults to filament 1. Bambu Studio’s filament inheritance code
Consider an object assigned to white filament 1. One of its parts has an explicit assignment to red filament 2.
An unpainted surface on that part stays red. A region painted with filament 1 becomes white. Changing the object’s default filament should not override either the part’s explicit assignment or the painted region.
A part setting of zero deserves particular attention. It means inheritance at this boundary. Treating it as an explicit assignment to filament 1 breaks projects whose parent object uses another filament.
After resolving the filament, the viewer can look up its display color in the project palette. Orca describes filament_colour as a visual aid. The project filament entry is the identity; the RGB value is its displayed swatch. Two filament entries can share a color while carrying different material settings. OrcaSlicer’s filament color definition
This is why “give each object a material” is insufficient for a painted project. The renderer needs the object and part defaults, then the surface-level overrides. Flatten those distinctions too early and the information needed to reproduce the appearance is gone.
4. Plate reconstruction starts with instance membership
A mesh has coordinates. A plate has project meaning.
Trying to recover plates by grouping nearby geometry can seem reasonable when the slicer displays several beds across its workspace. It becomes unreliable as soon as instances move, copies share geometry, or an object sits outside the expected bed area.
The saved plate relationships provide a better starting point.
Plate membership does not define the bed outline or workspace grid. Reproducing the slicer's layout also requires the printer's printable area and the slicer's plate-placement rules.
In model_settings.config, a plate can contain entries like this:
<plate>
<metadata key="plater_id" value="1"/>
<metadata key="plater_name" value="Housing"/>
<model_instance>
<metadata key="object_id" value="10"/>
<metadata key="instance_id" value="0"/>
<metadata key="identify_id" value="107"/>
</model_instance>
</plate>
object_id identifies the serialized model object. instance_id identifies a particular instance of that object. identify_id is a separate slicer identifier. The object-and-instance pair is the membership relationship to retain. OrcaSlicer’s plate serialization
That distinction matters whenever a project contains copies. A map from object ID to plate can represent only one assignment. A map from object-and-instance to plate can preserve separate placements of the same object.
Indexing also crosses several conventions. Saved plater_id values and familiar plate_N.* filenames are normally one-based, while instance ordinals are zero-based. Normalize those values deliberately when building an internal representation.
Once the plate list and membership exist, attach the supporting artifacts.
Common filenames include Metadata/plate_N.png, Metadata/plate_N.json, and Metadata/plate_N.gcode. The archive may also include alternate plate views such as top or unlit images. Plate configuration can reference artifact paths explicitly, so those references should take precedence over guessing filenames. OrcaSlicer’s plate artifact definitions
The PNG supplies a saved view. It cannot establish which instances belong to the plate.
The JSON supplies more useful detail, but its bounds need careful interpretation. Orca’s BBoxData describes a first-layer bounding box as [minX, minY, maxX, maxY], alongside first-layer area, layer height, and an object name. PlateBBoxData adds fields such as bbox_all, bbox_objects, filament IDs and colors, bed type, nozzle diameter, and first-layer time. Its aggregate bounds can include brim. OrcaSlicer’s plate bounding-box structures
Those are print-footprint facts. They do not define the printer’s bed outline or the full three-dimensional bounds of an overhanging model.
slice_info.config adds the saved slice results. A shortened plate record might look like this:
<plate>
<metadata key="index" value="1"/>
<metadata key="prediction" value="7200"/>
<metadata key="weight" value="42.5"/>
<filament
id="1"
type="PLA"
color="#FFFFFF"
used_m="14.2"
used_g="42.5"/>
</plate>
In these records, prediction is estimated print time in seconds and weight is estimated filament weight in grams. The per-filament fields used_m and used_g record meters and grams. Summary plate blocks depend on valid slice results, so an unsliced plate may have no corresponding result block. Bambu Studio’s slice-info exporter
These numbers describe a saved calculation. Orca obtains the time from its normal-mode estimate and the weight from print statistics. They are not measurements from a completed print. OrcaSlicer’s plate export code
A reader should also keep configured filaments separate from reported consumption. The project palette describes available filament entries. Surface assignments describe model appearance. Slice results describe what the saved toolpaths consume. Surface color coverage alone cannot tell you the weight used for infill, supports, or filament changes.
A practical reconstruction order is to load the saved plates and their instance memberships first, resolve the geometry for those instances, then attach whatever images and slice results are available.
Missing results should remain missing. They should not turn into zero-minute prints or cause plates to disappear.
Suppose a project declares four plates, but only plates 2 and 3 have saved slice summaries. The reconstructed project still has four plates. Plates 1 and 4 retain their assigned instances; their print time and filament consumption remain unknown.
Figure 3. Shared geometry, separate instance memberships, and optional slice results. The diagram shows relationships rather than slicer workspace coordinates.
Moving one of those instances to another plate can leave its mesh data unchanged. The project relationship changes, and its placement may change, but the underlying shape can remain identical. That is the distinction a reader has to preserve: the mesh describes the part, while the plate records how that particular copy participates in the print project.
This article was created with the help of AI.
來源:DEV Community · dev.to


