从通用 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();

Print3DModel 对象现在应修复并可打印。 使用 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 参数将 Printing3D3MFPackage 发送到管道。 Print3DTaskRequestedEventArgs 类型有一个属性:请求。 它的类型为 Print3DTaskRequest ,表示一个打印作业请求。 其方法 CreateTask 允许应用提交打印作业的正确信息,并返回对 3D 打印管道中发送的 Print3DTask 对象的引用

CreateTask 具有以下输入参数:打印作业名称的字符串、要使用的打印机 ID 的字符串,以及 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 打印对话框。

在这里,我们将方法注册 MyTaskRequestedTaskRequested 事件。

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打印 3D 生成 3MF 包
3D 打印 UWP 示例