3D printing from your Universal Windows Platform app

Learn how to add 3D printing functionality to your Universal Windows Platform (UWP) app.

This topic covers how to load 3D geometry data into your app and launch the 3D print dialog after ensuring your 3D model is printable and in the correct format. For a working example of these procedures, see the 3D printing UWP sample.

Important APIs

Setup

Add the Windows.Graphics.Printing3D namespace to your application class that requires 3D print functionality.

using Windows.Graphics.Printing3D;

The following namespaces will also be used in this guide.

using System;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

Next, give your class helpful member fields.

  • Declare a Print3DTask object to represent the printing task to be passed to the print driver.
  • Declare a StorageFile object to hold the original 3D data file that will be loaded into the app.
  • Declare a Printing3D3MFPackage object to represent a print-ready 3D model with all necessary metadata.
private Print3DTask printTask;
private StorageFile file;
private Printing3D3MFPackage package = new Printing3D3MFPackage();

Create a simple UI

This sample uses a Load button to bring a file into program memory, a Fix button to make any needed modifications to the file, and a Print button to initiate the print job. The following code creates these buttons (with their on-click event handlers) in the corresponding XAML file of your .cs class.

<StackPanel Orientation="Vertical" VerticalAlignment="Center">
    <Button x:Name="loadbutton" Content="Load Model from File" HorizontalAlignment="Center" Margin="5,5,5,5" VerticalAlignment="Center" Click="OnLoadClick"/>
    <Button x:Name="fixbutton" Content="Fix Model" HorizontalAlignment="Center" Margin="5,5,5,5" VerticalAlignment="Center" Click="OnFixClick"/>
    <Button x:Name="printbutton" Content="Print" HorizontalAlignment="center" Margin="5,5,5,5" VerticalAlignment="Center" Click="OnPrintClick"/>

The sample also includes a TextBlock for UI feedback.

    <TextBlock x:Name="OutputTextBlock" TextAlignment="Center"></TextBlock>
</StackPanel>

Get the 3D data

The method by which your app acquires 3D geometry data can vary. Your app may retrieve data from a 3D scan, download model data from a web resource, or generate a 3D mesh programmatically using mathematical formulas or user input. Here, we show how to load a 3D data file (of any of several common file types) into program memory from device storage. The 3D Builder model library provides a variety of models for you to download.

In the OnLoadClick method, the FileOpenPicker class loads a single file into app memory.

The following code shows how to load a single file into app memory using the FileOpenPicker class in the OnLoadClick method.

private async void OnLoadClick(object sender, RoutedEventArgs e) {

    FileOpenPicker openPicker = new FileOpenPicker();

    // allow common 3D data file types
    openPicker.FileTypeFilter.Add(".3mf");
    openPicker.FileTypeFilter.Add(".stl");
    openPicker.FileTypeFilter.Add(".ply");
    openPicker.FileTypeFilter.Add(".obj");

    // pick a file and assign it to this class' 'file' member
    file = await openPicker.PickSingleFileAsync();
    if (file == null) {
        return;
    }

Use 3D Builder to convert to 3D Manufacturing Format (.3mf)

3D geometry data can come in many different formats, and not all are efficient for 3D printing. Windows uses the 3D Manufacturing Format (.3mf) file type for all 3D printing tasks.

See the 3MF Specification to learn more about 3MF and the supported features for producers and consumers of 3D product. To learn how to utilize these features with Windows APIs, see the Generate a 3MF package tutorial.

Note

The 3D Builder app can open files of most popular 3D formats and save them as .3mf files. It also provides tools to edit your models, add color data, and perform other print-specific operations.

In this example, where the file type could vary, you could open the 3D Builder app and prompt the user to save the imported data as a .3mf file and then reload it.

    // if user loaded a non-3mf file type
    if (file.FileType != ".3mf") {

        // elect 3D Builder as the application to launch
        LauncherOptions options = new LauncherOptions();
        options.TargetApplicationPackageFamilyName = "Microsoft.3DBuilder_8wekyb3d8bbwe";

        // Launch the retrieved file in 3D builder
        bool success = await Windows.System.Launcher.LaunchFileAsync(file, options);

        // prompt the user to save as .3mf
        OutputTextBlock.Text = "save " + file.Name + " as a .3mf file and reload.";
        
        // have user choose another file (ideally the newly-saved .3mf file)
        file = await openPicker.PickSingleFileAsync();

    } else {
        // if the file type is .3mf
        // notify user that load was successful
        OutputTextBlock.Text = file.Name + " loaded as file";
    }
}

Repair model data for 3D printing

Not all 3D model data is printable, even in the .3mf type. In order for the printer to correctly determine what space to fill and what to leave empty, each model to be printed must be a single seamless mesh, have outward-facing surface normals, and have manifold geometry. Issues in these areas can arise in a variety of different forms and can be hard to spot in complex shapes. However, modern software solutions are often adequate for converting raw geometry to printable 3D shapes. This is known as repairing the model and is implemented in the OnFixClick method shown here.

Note

The 3D data file must be converted to implement IRandomAccessStream, which can then be used to generate a Printing3DModel object.

private async void OnFixClick(object sender, RoutedEventArgs e) {

    // read the loaded file's data as a data stream
    IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read);

    // assign a Printing3DModel to this data stream
    Printing3DModel model = await package.LoadModelFromPackageAsync(fileStream);

    // use Printing3DModel's repair function
    OutputTextBlock.Text = "repairing model";
    var data = model.RepairAsync();

The Printing3DModel object should now be repaired and printable. Use SaveModelToPackageAsync to assign the model to the Printing3D3MFPackage object that you declared when creating the class.

    // save model to this class' Printing3D3MFPackage
    OutputTextBlock.Text = "saving model to 3MF package";
    await package.SaveModelToPackageAsync(model);

}

Execute printing task: create a TaskRequested handler

Later, when the 3D print dialog is displayed to the user and the user elects to begin printing, your app will need to pass in the desired parameters to the 3D print pipeline. The 3D print API will raise the TaskRequested event, which requires handling appropriately.

private void MyTaskRequested(Print3DManager sender, Print3DTaskRequestedEventArgs args) {

The core purpose of this method is to use the args parameter to send a Printing3D3MFPackage down the pipeline. The Print3DTaskRequestedEventArgs type has one property: Request. It is of the type Print3DTaskRequest and represents one print job request. Its method CreateTask lets the app submit the correct information for your print job and return a reference to the Print3DTask object that was sent down the 3D print pipeline.

CreateTask has the following input parameters: a string for the print job name, a string for the ID of the printer to use, and a Print3DTaskSourceRequestedHandler delegate. The delegate is automatically invoked when the 3DTaskSourceRequested event is raised (this is done by the API itself). The important thing to note is that this delegate is invoked when a print job is initiated, and it is responsible for providing the right 3D print package.

Print3DTaskSourceRequestedHandler takes one parameter, a Print3DTaskSourceRequestedArgs object, which contains the data to be sent. The SetSource method accepts the package to be printed. The following code shows a Print3DTaskSourceRequestedHandler delegate implementation (sourceHandler).

// this delegate handles the API's request for a source package
Print3DTaskSourceRequestedHandler sourceHandler = delegate (Print3DTaskSourceRequestedArgs sourceRequestedArgs) {
    sourceRequestedArgs.SetSource(package);
};

Next, call CreateTask, using the newly-defined delegate.

// the Print3DTaskRequest ('Request'), a member of 'args', creates a Print3DTask to be sent down the pipeline.
printTask = args.Request.CreateTask("Print Title", "Default", sourceHandler);

The Print3DTask returned is assigned to the class variable declared in the beginning. This reference can be used to handle certain events thrown by the task.

// optional events to handle
printTask.Completed += Task_Completed; 
printTask.Submitting += Task_Submitting;

Note

You must implement a Task_Submitting and Task_Completed method if you wish to register them to these events.

Execute printing task: open 3D print dialog

Finally, you need to launch the 3D print dialog that provides a number of printing options.

Here, we register a MyTaskRequested method with the TaskRequested event.

private async void OnPrintClick(object sender, RoutedEventArgs e) {

    // get a reference to this class' Print3DManager
    Print3DManager myManager = Print3DManager.GetForCurrentView();

    // register the method 'MyTaskRequested' to the Print3DManager's TaskRequested event
    myManager.TaskRequested += MyTaskRequested;

After registering the TaskRequested event handler, you can invoke the method ShowPrintUIAsync, which brings up the 3D print dialog in the current application window.

// show the 3D print dialog
OutputTextBlock.Text = "opening print dialog";
var result = await Print3DManager.ShowPrintUIAsync();

It is also good practice to de-register your event handlers once your app resumes control.

    // remove the print task request after dialog is shown            
    myManager.TaskRequested -= MyTaskRequested;
}

3D printing with Windows 10 Generate a 3MF package
3D printing UWP sample