Slicer Project Compilers#

Intro#

Slicer project compilers turn prepared OpenVCAD designs into slicer-native .3mf project files for filament printing workflows. Use them when you want OpenVCAD to generate geometry regions and attribute-derived assignments, while the downstream slicer still owns slicing, preview, and G-code generation.

There are two separate workflows:

Workflow

Input attributes

Output project

Best fit

PrusaSlicer settings meshes

Scalar planning attributes such as INFILL_DENSITY, FUZZY_SKIN_POINT_DISTANCE, LAYER_HEIGHT, or PERIMETER_SPEED

PrusaSlicer-style .3mf

Spatially varying slicer planning settings

PrusaSlicer virtual extrusion

TEMPERATURE with optional companion FLOW_RATE

PrusaSlicer-style .3mf with logical tools and toolchange G-code

Machine-state changes at region boundaries

PrusaSlicer ColorMix color

COLOR_RGB

PrusaSlicer-style .3mf with ColorMix virtual extruders

Mixed-filament color approximation from design-space colors

PrusaSlicer ColorMix material fractions

VOLUME_FRACTIONS plus volume_fraction_materials

PrusaSlicer-style .3mf with ColorMix virtual extruders

Direct material-fraction to filament-slot recipes

FullSpectrum color

COLOR_RGB

Orca / Bambu-style Full Spectrum .3mf

Mixed-filament color approximation from design-space colors

FullSpectrum material fractions

VOLUME_FRACTIONS plus volume_fraction_materials

Orca / Bambu-style Full Spectrum .3mf

Direct material-fraction to filament-slot recipes

For slice-image workflows instead of slicer projects, see Material Inkjet, Color Inkjet, and VAT Photo.

Prerequisites#

Shared 3MF Concepts#

A 3MF file is a compressed package, not a single flat mesh file. Conceptually it behaves like a ZIP / OPC-style container with relationship files, content-type metadata, and XML model parts. The core model part stores triangle meshes as XML vertices and triangles. Slicers extend the package by adding their own project settings and per-model metadata.

Typical package shapes:

generic_part.3mf
  [Content_Types].xml
  _rels/.rels
  3D/3dmodel.model

prusa_project.3mf
  3D/3dmodel.model
  Metadata/Slic3r_PE.config
  Metadata/Slic3r_PE_model.config

prusa_colormix_project.3mf
  3D/3dmodel.model
  Metadata/Slic3r_PE_model.config
  Metadata/Prusa_Slicer_full_spectrum.json

orca_full_spectrum_project.3mf
  3D/3dmodel.model
  Metadata/project_settings.config
  Metadata/model_settings.config

A very small 3MF mesh fragment looks like this:

<model unit="millimeter" xml:lang="en-US"
       xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02">
  <resources>
    <object id="1" type="model">
      <mesh>
        <vertices>
          <vertex x="0" y="0" z="0"/>
          <vertex x="20" y="0" z="0"/>
          <vertex x="0" y="20" z="0"/>
        </vertices>
        <triangles>
          <triangle v1="0" v2="1" v3="2"/>
        </triangles>
      </mesh>
    </object>
  </resources>
</model>

The extra value of slicer project 3MFs comes from the attachments around that core mesh. A PrusaSlicer project can carry Prusa project configuration and per-volume settings. An Orca / Bambu-style project can carry model settings, project settings, and component assignments that tell the slicer which extruder or virtual mixed filament belongs to each region.

For the 3MF container and core mesh format, see the 3MF Consortium specification page and the Core 3MF Specification.

PrusaSlicer#

Use the PrusaSlicer compiler when your OpenVCAD design carries scalar process attributes and you want a PrusaSlicer-compatible project file. The compiler samples scalar attributes over the solid, partitions the sampled field into a finite number of regions, emits a mesh for each region, and writes a PrusaSlicer-style .3mf.

The important idea is that a continuous OpenVCAD field becomes piecewise constant slicer regions. Each generated region gets one representative value. More regions preserve more variation, but they also create more sub-volumes for PrusaSlicer to manage.

Opening The Project#

The compiler only writes the .3mf. It does not launch PrusaSlicer.

  1. Run your Python script so compile() finishes and the .3mf path exists.

  2. Open PrusaSlicer, use File -> Import, and select the generated .3mf.

  3. Inspect sub-volumes and per-volume settings in the Plater / Models UI, then slice and review the G-code preview.

Settings Applied To Meshes#

The settings-mesh path is for attributes that directly affect slicer planning. These settings change how PrusaSlicer computes toolpaths: infill density, layer height, perimeter counts, line widths, and feature speeds. OpenVCAD emits sub-volumes, and each sub-volume carries Prusa-compatible metadata for the selected slicer setting.

This path is appropriate when the parameter should influence slicing decisions before G-code is generated. For example, an INFILL_DENSITY gradient changes how dense the internal infill toolpaths are in each generated region.

Settings-mesh attributes are scalar fields. The Python names below are available under pv.DefaultAttributes.

Attribute

PrusaSlicer setting key

Typical use

INFILL_DENSITY

fill_density

Spatial infill percentage

FUZZY_SKIN_POINT_DISTANCE

fuzzy_skin_point_dist

Spatial fuzzy skin roughness

BRIDGE_SPEED

bridge_speed

Bridge planning speed

EXTERNAL_PERIMETER_EXTRUSION_WIDTH

external_perimeter_extrusion_width

Outer wall line width

EXTERNAL_PERIMETER_SPEED

external_perimeter_speed

Outer wall speed

EXTRUSION_WIDTH

extrusion_width

General line width

GAP_FILL_SPEED

gap_fill_speed

Gap fill speed

INFILL_EXTRUSION_WIDTH

infill_extrusion_width

Infill line width

INFILL_SPEED

infill_speed

Infill speed

IRONING_FLOWRATE

ironing_flowrate

Ironing flow

IRONING_SPEED

ironing_speed

Ironing speed

LAYER_HEIGHT

layer_height

Region layer height

PERIMETER_EXTRUSION_WIDTH

perimeter_extrusion_width

Perimeter line width

PERIMETER_SPEED

perimeter_speed

Perimeter speed

PERIMETERS

perimeters

Perimeter count

SMALL_PERIMETER_SPEED

small_perimeter_speed

Small-feature perimeter speed

SOLID_INFILL_EXTRUSION_WIDTH

solid_infill_extrusion_width

Solid infill line width

SOLID_INFILL_SPEED

solid_infill_speed

Solid infill speed

SUPPORT_MATERIAL_EXTRUSION_WIDTH

support_material_extrusion_width

Support extrusion width

TOP_INFILL_EXTRUSION_WIDTH

top_infill_extrusion_width

Top infill line width

TOP_SOLID_INFILL_SPEED

top_solid_infill_speed

Top solid infill speed

Fuzzy skin cylinder (01_fuzzy_skin_cylinder.py): this example applies FUZZY_SKIN_POINT_DISTANCE along the cylinder height and writes output/fuzzy_skin_cylinder.3mf. The generated sub-volumes carry fuzzy_skin_point_dist overrides, so PrusaSlicer changes the planned surface texture by region.

cylinder.set_attribute(
    pv.DefaultAttributes.FUZZY_SKIN_POINT_DISTANCE,
    pv.FloatAttribute(fuzzy_expr),
)

compiler = pvc.PrusaSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    num_regions=12,
)

OpenVCAD (fuzzy skin distance)

OpenVCAD render of fuzzy skin point distance on a cylinder

PrusaSlicer preview (model and fuzzy skin G-code texture)

PrusaSlicer G-code preview showing fuzzy skin

Models / sub-volumes (fuzzy skin overrides)

PrusaSlicer models list with per-volume fuzzy skin

Infill density bar (02_infill_density_bar.py): this example ramps INFILL_DENSITY along the bar and writes output/infill_density_bar.3mf. The generated regions carry fill_density metadata, so PrusaSlicer computes denser or sparser infill toolpaths in each region.

bar.set_attribute(
    pv.DefaultAttributes.INFILL_DENSITY,
    pv.FloatAttribute(infill_expr),
)

compiler = pvc.PrusaSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    num_regions=12,
)

OpenVCAD (infill density)

OpenVCAD render of infill density gradient on a bar

PrusaSlicer G-code preview (infill gradient cutaway)

PrusaSlicer G-code preview with infill density gradient

Virtual Extrusion#

Virtual extrusion controls machine state by taking advantage of slicer toolchange events. OpenVCAD assigns synthetic extruder indices to regions, patches the project profile to declare those logical tools, and provides toolchange G-code that applies the desired process commands when the slicer switches between regions.

The logical toolhead does not need to correspond to a separate physical nozzle. On a single-tool printer, the slicer can still emit toolchange events between logical tools, and the toolchange script can update temperature, flow, or other machine state without changing filament. On a multi-tool printer, the same concept can coexist with physical tool changes if the printer profile and script are written that way.

This path is intentionally different from settings meshes:

Path

Controls

Slicer sees it before planning?

Best fit

Settings mesh

Toolpath planning settings

Yes

Infill, speeds, widths, layer height, perimeters

Virtual extrusion

Machine state commands

No, it runs as G-code

Temperature, flow, and process state that can be changed at region boundaries

In the current method, TEMPERATURE is the primary virtual-extrusion attribute and FLOW_RATE is its companion.

Attribute

Role

Effect

TEMPERATURE

Primary region attribute

Creates logical tools and emits M104 temperatures through toolchange G-code

FLOW_RATE

Companion attribute

Supplies M221 flow values for the same logical toolchange events

The toolchange script applies commands such as:

M104 S{temperature}
M221 S{flow_rate}

Temperature and flow example (03_temperature_compensation_demo.py): this example applies a TEMPERATURE field, derives FLOW_RATE from a lookup table, and writes output/temperature_compensation_demo.3mf. The compiler uses Prusa profile files from examples/applications/foaming_filaments/profiles/ so the generated project can define logical tools and toolchange G-code.

rect_prism.set_attribute(
    pv.DefaultAttributes.TEMPERATURE,
    pv.FloatAttribute("max(min((x/3+236),256),216)"),
)

compiler = pvc.PrusaSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    num_regions=10,
    printer_profile_path=printer_profile_path,
    filament_profile_path=filament_profile_path,
)

OpenVCAD (temperature)

OpenVCAD render of temperature field on a bar

PrusaSlicer G-code preview (temperature)

PrusaSlicer G-code preview colored by temperature

ColorMix#

PrusaSlicer ColorMix uses Prusa’s FullSpectrum project metadata and Prusa_Slicer_full_spectrum.json to define virtual extruders whose IDs start after the physical filament slots. OpenVCAD assigns generated color/material regions to those physical or virtual extruder IDs in the normal Prusa Slic3r_PE_model.config metadata.

ColorMix mode is mutually exclusive with the scalar settings-mesh and virtual-extrusion paths. It is selected automatically when the design contains COLOR_RGB or VOLUME_FRACTIONS, or explicitly with enable_color_mix=True.

For COLOR_RGB, OpenVCAD uses a device-aware recipe selector. It generates valid Prusa ColorMix recipes from the configured physical filaments, predicts each recipe’s apparent color with Prusa’s mixer model, and then selects up to max_palette_size printable recipes that best cover the sampled design colors. max_palette_size counts both direct physical filament colors and virtual mixed recipes. The generated 3MF also includes Metadata/OpenVCAD_prusa_colormix_report.json, which records the selected recipes and DeltaE fit summary for inspection.

Color gradient example (06_prusa_colormix_color_gradient.py): this example applies a COLOR_RGB ramp and writes output/prusa_colormix_color_gradient.3mf.

bar.set_attribute(
    pv.DefaultAttributes.COLOR_RGB,
    pv.Vec3Attribute(red_expr, green_expr, blue_expr),
)

compiler = pvc.PrusaSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    enable_color_mix=True,
    color_mix_recipe_preset="expanded",
    max_palette_size=10,
    min_component_percent=15,
    max_recipe_components=3,
    region_overlap_mm=0.2,
)

Volume-fraction example (07_prusa_colormix_volume_fractions.py): this example maps OpenVCAD materials directly to physical filament slots and writes output/prusa_colormix_volume_fractions.3mf.

compiler = pvc.PrusaSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    enable_color_mix=True,
    total_physical_extruders=5,
    color_mix_filaments=[
        {"slot": 1, "color_hex": "#FF0000"},
        {"slot": 2, "color_hex": "#0000FF"},
    ],
    volume_fraction_materials={"red": 1, "blue": 2},
    max_palette_size=10,
    min_component_percent=1,
    max_recipe_components=3,
    region_overlap_mm=0.0,
)

Prusa Constructor Options#

compiler = pvc.PrusaSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    num_regions=12,
    printer_profile_path=printer_profile_path,
    filament_profile_path=filament_profile_path,
    enable_color_mix=False,
    color_mix_filaments=None,
    total_physical_extruders=5,
    color_mix_recipe_preset="expanded",
    max_palette_size=32,
    min_component_percent=15,
    max_recipe_components=3,
    direct_physical_delta_e=1.0,
    region_overlap_mm=0.2,
    volume_fraction_materials={},
    material_defs_path="",
)
compiler.compile()

Option

Meaning

root

The OpenVCAD design tree to compile.

voxel_size

Sampling spacing in mm. Smaller values resolve smaller regions but cost more time and memory.

output_file_path

Destination .3mf project path.

num_regions

Number of value bands for each scalar attribute. More regions preserve more variation but create more sub-volumes.

printer_profile_path

PrusaSlicer printer .ini. Required when virtual extrusion attributes are present.

filament_profile_path

PrusaSlicer filament .ini. Required when virtual extrusion attributes are present.

enable_color_mix

Explicitly enables Prusa ColorMix mode. COLOR_RGB or VOLUME_FRACTIONS also selects it automatically.

color_mix_filaments

Physical filament slots and colors for ColorMix. Each dictionary may include slot, color_hex, and nozzle_diameter_mm. Empty uses Prusa CMYKW defaults for COLOR_RGB: #0082ad, #d10f4f, #efd00b, #3d3e3d, #e6eaef.

total_physical_extruders

Total physical tool slots in PrusaSlicer. Virtual ColorMix extruders start after this count, so unused physical tool IDs can be skipped. Defaults to 5.

color_mix_recipe_preset

Recipe vocabulary for Prusa COLOR_RGB ColorMix. conservative uses base colors plus 25/75, 50/50, and 75/25 pair blends. expanded also includes 50/25/25 three-filament rotations.

max_palette_size

Maximum generated ColorMix palette size or volume-fraction recipe-region count. For Prusa COLOR_RGB, this counts both physical base colors and virtual mixed recipes.

min_component_percent

Minimum component percentage kept in generated ColorMix recipes.

max_recipe_components

Maximum physical filaments allowed in one Prusa ColorMix recipe. Prusa ColorMix supports up to 3.

direct_physical_delta_e

Legacy setting retained for compatibility. Prusa COLOR_RGB ColorMix now chooses physical colors and virtual recipes from the same device-aware candidate set.

region_overlap_mm

Small overlap between generated ColorMix sub-parts to avoid visible cracks between separately meshed regions.

volume_fraction_materials

Material-name to physical-slot mapping for direct VOLUME_FRACTIONS export, such as {"red": 1, "blue": 2}.

material_defs_path

Optional MaterialDefs JSON path. Empty uses the bundled default material definitions.

FullSpectrum#

Use the FullSpectrum compiler when your OpenVCAD design carries either COLOR_RGB or VOLUME_FRACTIONS and you want an Orca / Bambu-style project for the FullSpectrum workflow.

Full Spectrum is a slicer workflow for getting more apparent colors out of a limited set of loaded filaments. Instead of truly melting filaments together into a homogeneous mixed polymer, it creates virtual mixed-color filaments by alternating physical filaments through layer dithering or related patterns. Thin layers and partially translucent filament let light interact with multiple colors, so the eye sees an intermediate color.

The achievable colors depend strongly on the actual filaments loaded in the printer, their translucency, layer height, surface orientation, and slicer settings. A CMYKW physical set, cyan, magenta, yellow, black, and white, is the recommended starting point because it gives the color-matching algorithm a broad gamut to work with.

OpenVCAD targets the OrcaSlicer-FullSpectrum community fork for this project format. Treat this as an emerging ecosystem: the generated projects use Orca / Bambu-style metadata and FullSpectrum mixed-filament settings, and stock PrusaSlicer, stock OrcaSlicer, or stock Bambu Studio may not interpret those settings correctly.

COLOR_RGB Workflow#

Use COLOR_RGB when the design field is an intended color. The compiler samples the RGB target field, reduces it to a bounded palette with max_palette_size, compares each palette color against the loaded physical filaments and possible mixed-filament recipes, and assigns each generated mesh region to a physical or virtual mixed filament.

The default physical palette for COLOR_RGB mode is CYMKW if you do not pass filaments. Pass explicit filament dictionaries when your loaded spool colors differ.

compiler = pvc.FullSpectrumSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    [
        {"slot": 1, "color_hex": "#00FFFF"},
        {"slot": 2, "color_hex": "#FF00FF"},
        {"slot": 3, "color_hex": "#FFFF00"},
        {"slot": 4, "color_hex": "#000000"},
        {"slot": 5, "color_hex": "#FFFFFF"},
    ],
    max_palette_size=32,
    min_component_percent=15,
    max_recipe_components=5,
)

Color gradient example (04_full_spectrum_color_gradient.py): this example applies a COLOR_RGB ramp from cyan toward magenta and writes output/full_spectrum_color_gradient.3mf. The compiler samples the RGB target field, reduces it to a small palette, and assigns each palette color to a physical or virtual mixed filament recipe.

bar.set_attribute(
    pv.DefaultAttributes.COLOR_RGB,
    pv.Vec3Attribute(red_expr, green_expr, blue_expr),
)

compiler = pvc.FullSpectrumSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    max_palette_size=10,
    min_component_percent=15,
    max_recipe_components=5,
)

OpenVCAD (COLOR_RGB target)

OpenVCAD render of FullSpectrum color gradient swatch

OrcaSlicer-FullSpectrum g-code screenshot

OrcaSlicer FullSpectrum color gradient screenshot

VOLUME_FRACTIONS Workflow#

Use VOLUME_FRACTIONS when the OpenVCAD field already describes material proportions and you want those proportions to become FullSpectrum recipe weights. This is simpler than color matching because the design says which materials should participate.

The compiler maps OpenVCAD material names to physical filament slots with volume_fraction_materials, normalizes the mapped fractions for each sample, clusters fraction vectors into at most max_palette_size recipe regions, and emits physical or virtual mixed-filament recipes using representative weights for each region.

compiler = pvc.FullSpectrumSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    volume_fraction_materials={"red": 1, "blue": 2},
    max_palette_size=10,
    min_component_percent=1,
    max_recipe_components=5,
)

Volume-fraction example (05_full_spectrum_volume_fractions.py): this example ramps red and blue material fractions across the bar and writes output/full_spectrum_volume_fractions.3mf. The volume_fraction_materials={"red": 1, "blue": 2} mapping sends those OpenVCAD material names directly to physical filament slots.

bar.set_attribute(
    pv.DefaultAttributes.VOLUME_FRACTIONS,
    pv.VolumeFractionsAttribute(
        [
            (red_fraction_expr, materials.id("red")),
            (blue_fraction_expr, materials.id("blue")),
        ]
    ),
)

compiler = pvc.FullSpectrumSlicerProjectCompiler(
    root,
    pv.Vec3(0.25, 0.25, 0.25),
    out_3mf,
    volume_fraction_materials={"red": 1, "blue": 2},
    max_palette_size=10,
    min_component_percent=1,
    max_recipe_components=5,
)

OpenVCAD (VOLUME_FRACTIONS target)

OpenVCAD render of FullSpectrum volume-fraction swatch

OrcaSlicer-FullSpectrum g-code screenshot

OrcaSlicer FullSpectrum volume-fraction screenshot

FullSpectrum Constructor Options#

compiler = pvc.FullSpectrumSlicerProjectCompiler(
    root,
    voxel_size,
    output_file_path,
    filaments=None,
    max_palette_size=32,
    min_component_percent=15,
    max_recipe_components=5,
    direct_physical_delta_e=1.0,
    region_overlap_mm=0.2,
    base_project_settings_path="",
    orca_machine_profile_path="",
    orca_process_profile_path="",
    orca_default_filament_profile_path="",
    orca_profile_search_paths=[],
    volume_fraction_materials={},
    material_defs_path="",
)

Option

Meaning

filaments

Physical filament slots and colors. Each dictionary may include slot, color_hex, filament_settings_id, filament_id, filament_profile_path, and nozzle_diameter_mm.

max_palette_size

Maximum generated COLOR_RGB palette size or VOLUME_FRACTIONS recipe-region count.

min_component_percent

Minimum component percentage kept in generated mixed recipes. Tiny components are dropped and the remaining weights are normalized.

max_recipe_components

Maximum physical filaments allowed in one mixed recipe.

direct_physical_delta_e

DeltaE threshold for assigning a COLOR_RGB target directly to a physical filament instead of creating a mixed recipe.

region_overlap_mm

Small overlap between generated FullSpectrum sub-parts to avoid visible cracks between separately meshed regions.

base_project_settings_path

Optional Orca project settings JSON to merge before compiler-controlled FullSpectrum keys are written.

orca_machine_profile_path

Optional Orca machine profile path or resolvable profile name.

orca_process_profile_path

Optional Orca process profile path or resolvable profile name.

orca_default_filament_profile_path

Optional default filament profile path or resolvable profile name.

orca_profile_search_paths

Additional directories searched for Orca JSON profiles.

volume_fraction_materials

Material-name to physical-slot mapping for direct VOLUME_FRACTIONS export, such as {"red": 1, "blue": 2}.

material_defs_path

Optional MaterialDefs JSON path. Empty uses the bundled default material definitions.

FullSpectrum Limitations#

  • FullSpectrum is not true molten filament mixing. It is an optical and geometric approximation based on alternating physical filaments.

  • The reachable color gamut depends on the loaded filaments, translucency, layer height, top/bottom shell behavior, and surface orientation.

  • OpenVCAD emits a finite number of mesh regions. More regions can preserve more variation, but they also increase project complexity.

  • Sloped surfaces, small details, top layers, and short regions can show different color behavior than tall vertical walls.

  • Stock slicers may ignore or reject FullSpectrum metadata. Use the documented FullSpectrum fork unless you have verified another slicer version.

  • max_recipe_components and min_component_percent intentionally bound recipe complexity. Some requested colors or material blends cannot be represented within those limits.