从通用 Windows 平台应用进行 3D 打印

了解如何将 3D 打印功能添加到通用 Windows 平台 (UWP) 应用。

本主题介绍在确保 3D 模型可打印并且格式正确之后,如何将 3D 几何数据加载到应用中以及如何启动 3D 打印对话框, 有关这些过程的工作示例,请参阅 3D 打印 UWP 示例

重要的 API

设置

Windows.Graphics.Printing3D 命名空间添加到需要 3D 打印功能的应用程序类。

using Windows.Graphics.Printing3D;

本指南中还将使用以下命名空间。

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;

接下来,为你的类提供有用的成员字段。

  • 声明 Print3DTask 对象以表示要传递给打印驱动程序的打印任务。
  • 声明一个 StorageFile 对象以保留要加载到应用中的原始 3D 数据文件。
  • 声明 Printing3D3MFPackage 对象,以表示具有所有必要元数据的打印就绪 3D 模型。
private Print3DTask printTask;
private StorageFile file;
private Printing3D3MFPackage package = new Printing3D3MFPackage();

创建一个简单的 UI

此示例使用 “加载 ”按钮将文件引入程序内存,使用 “修复” 按钮对文件进行任何所需的修改,并使用 “打印 ”按钮启动打印作业。 以下代码在 .cs 类的相应 XAML 文件中创建这些按钮 (及其单击事件处理程序) 。

<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"/>

该示例还包括用于 UI 反馈的 TextBlock

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

获取 3D 数据

应用获取 3D 几何图形数据的方法可能有所不同。 应用可能从 3D 扫描检索数据、从 Web 资源下载模型数据或者使用数学公式或用户输入以编程方式生成 3D 网格。 在这里,我们将演示如何将 3D 数据文件 (从设备存储) 的几种常见文件类型中的任何一种加载到程序内存中。 3D Builder 模型库提供各种模型供你下载。

OnLoadClick在 方法中,FileOpenPicker 类将单个文件加载到应用内存中。

以下代码演示如何使用 方法中的 FileOpenPicker 类将单个文件加载到应用内存中 OnLoadClick

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;
    }

使用 3D Builder 转换为 3D 制造格式 (.3mf)

3D 几何图形数据可以采用许多不同的格式,并非所有数据都可用于 3D 打印。 Windows 对所有 3D 打印任务使用 3D 制造格式 (.3mf) 文件类型。

请参阅 3MF 规范 ,详细了解 3MF 以及 3D 产品的生产者和使用者支持的功能。 若要了解如何通过 Windows API 利用这些功能,请参阅 生成 3MF 包 教程。

注意

3D Builder 应用可以打开最常见 3D 格式的文件并将其另存为 .3mf 文件。 它还提供用于编辑模型、添加颜色数据以及执行其他特定于打印的操作的工具。

在此示例中,文件类型可能有所不同,可以打开 3D Builder 应用并提示用户将导入的数据另存为 .3mf 文件,然后重新加载它。

    // 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";
    }
}

修复模型数据以供 3D 打印

并非所有 3D 模型都可以打印,即使采用 .3mf 类型也是如此。 为了使打印机正确确定要填充的空间和留空空间,要打印的每个模型必须是单个无缝网格,具有向外表面法线,并且具有多形几何图形。 这些方面的问题可能会以各种各样的形式出现,而且在复杂的形状中难以发现。 不过,现代软件解决方案通常足以将原始几何图形转换为可打印的 3D 形状。 这称为 修复 模型,并在此处所示的 方法中 OnFixClick 实现。

注意

3D 数据文件必须经过转换才能实现 IRandomAccessStream,然后可以使用后者生成 Printing3DModel 对象。

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();

Printing3DModel 对象现在应已修复且可打印。 使用 SaveModelToPackageAsync 将模型分配给创建类时声明的 Printing3D3MFPackage 对象。

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

}

执行打印任务:创建一个 TaskRequested 处理程序

稍后,当向用户显示 3D 打印对话框并且用户选择开始打印时,应用需要将所需的参数传递到 3D 打印管道。 3D 打印 API 将引发 TaskRequested 事件,这需要适当处理。

private void MyTaskRequested(Print3DManager sender, Print3DTaskRequestedEventArgs args) {

此方法的核心用途是使用 args 参数沿管道发送 Printing3D3MFPackagePrint3DTaskRequestedEventArgs 类型有一个属性:Request。 它属于 Print3DTaskRequest 类型,表示一个打印作业请求。 其方法 CreateTask 允许应用为打印作业提交正确的信息,并返回对在 3D 打印管道中向下发送的 Print3DTask 对象的引用。

CreateTask 具有以下输入参数:一个用于打印作业名称的string、一个用于要使用的打印机 ID 的 string 和一个 Print3DTaskSourceRequestedHandler 委托。 引发 3DTaskSourceRequested 事件时会自动调用该委托(该操作由 API 本身完成)。 需要着重注意的是,该委托会在打印作业启动时调用,它负责提供正确的 3D 打印程序包。

Print3DTaskSourceRequestedHandler 采用一个参数 ,即 Print3DTaskSourceRequestedArgs 对象,其中包含要发送的数据。 SetSource 方法接受要打印的包。 下面的代码显示 Print3DTaskSourceRequestedHandler 委托实现 (sourceHandler) 。

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

接下来,使用新定义的委托调用 CreateTask

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

返回的 Print3DTask 分配给在开头声明的类变量。 此引用可用于处理任务引发的某些事件。

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

注意

必须实现 Task_SubmittingTask_Completed 方法才能向这些事件注册它们。

执行打印任务:打开 3D 打印对话框

最后,需要启动提供许多打印选项的 3D 打印对话框。

在这里,我们使用 TaskRequested 事件注册方法MyTaskRequested

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;

注册 TaskRequested 事件处理程序后,可以调用 ShowPrintUIAsync 方法,这将在当前应用程序窗口中显示 3D 打印对话框。

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

在应用恢复控制后,最好取消注册事件处理程序。

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

使用 Windows 10生成 3MF 包的 3D 打印
3D 打印 UWP 示例