從 app 進行 3D 列印3D printing from your app

重要 APIImportant APIs

了解如何將 3D 列印功能加入通用 Windows 應用程式。Learn how to add 3D printing functionality to your Universal Windows app. 本主題涵蓋如何將 3D 幾何資料載入 app,以及如何在確保 3D 模型為可列印且為正確的格式之後,啟動 3D 列印對話方塊。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. 如需這些程序運作的範例,請參閱 3D 列印 UWP 範例For a working example of these procedures, see the 3D printing UWP sample.

注意

為了保持簡潔,本指南中的範例程式碼、錯誤報告及處理已大幅簡化。In the sample code in this guide, error reporting and handling is greatly simplified for the sake of simplicity.

安裝程式Setup

在需要 3D 列印功能的應用程式類別中,加入 Windows.Graphics.Printing3D 命名空間。In your application class that is to have 3D print functionality, add the Windows.Graphics.Printing3D namespace.

using Windows.Graphics.Printing3D;

下列其他的命名空間,將會在這個指南中使用。The following additional namespaces will 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. 宣告 Print3DTask 物件以代表要傳遞至列印驅動程式的列印工作參考。Declare a Print3DTask object to represent the printing task that is to be passed to the print driver. 宣告 StorageFile 物件來保存將載入到 App 的原始 3D 資料檔案。Declare a StorageFile object to hold the original 3D data file that will be loaded into the app. 宣告 Printing3D3MFPackage 物件,這個物件代表含有所有必要中繼資料的列印就緒 3D 模型。Declare a Printing3D3MFPackage object, which represents a print-ready 3D model with all necessary metadata.

private Print3DTask printTask;
private StorageFile file;
private Printing3D3MFPackage package = new Printing3D3MFPackage();

建立簡單的 UICreate a simple UI

這個範例具備三個使用者控制項:將檔案帶入程式記憶體的 [載入] 按鈕、會視需要修改檔案的 [修正] 按鈕,以及初始化列印工作的 [列印] 按鈕。This sample features three user controls: a Load button which will bring a file into program memory, a Fix button which will modify the file as necessary, and a Print button which will initiate the print job. 下列程式碼會在您 .cs 類別對應的 XAML 檔案中建立這些按鈕 (包含其點擊事件處理常式)。The following code creates these buttons (with their on-click event handlers) in your .cs class' corresponding XAML file.

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

加入 TextBlock 以用於 UI 回饋。Add a TextBlock for UI feedback.

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

取得 3D 資料Get the 3D data

您的 App 取得 3D 幾何資料的方法會有差異。The method by which your app acquires 3D geometry data will vary. 您 App 擷取資料的方式可能是 3D 掃描、從網路資源下載模型資料,或以程式設計方式使用數學公式或使用者輸入來產生 3D 網格。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. 為了簡單起見,本指南會示範從裝置存放空間將 3D 資料檔案 (任何常見的檔案類型) 載入程式記憶體。For the sake of simplicity, this guide will show how to load a 3D data file (of any of several common file types) into program memory from device storage. 3D Builder 模型庫提供您輕鬆就能下載到裝置上的各種模型。The 3D Builder model library provides a variety of models that you can easily download to your device.

OnLoadClick 方法中,使用 FileOpenPicker 類別將單一檔案載入至 App 記憶體。In your OnLoadClick method, use the FileOpenPicker class to load a single file into your app's memory.

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)Use 3D Builder to convert to 3D Manufacturing Format (.3mf)

這時,您就可以將 3D 資料檔案載入 app 的記憶體。At this point, you are able to load a 3D data file into your app's memory. 不過,3D 幾何資料有許多不同格式,且對 3D 列印並非都有效率。However, 3D geometry data can come in many different formats, and not all are efficient for 3D printing. Windows 10 對於所有的 3D 列印工作皆使用 3D 製造格式 (.3mf) 檔案類型。Windows 10 uses the 3D Manufacturing Format (.3mf) file type for all 3D printing tasks.

注意

.3mf 檔案類型提供多於本教學課程可涵蓋的功能。The .3mf file type offers more functionality than is covered in this tutorial. 若要深入了解 3MF 及它提供給 3D 產品生產者與消費者的功能,請參閱 3MF 規格To learn more about 3MF and the features it provides to producers and consumers of 3D products, see the 3MF Specification. 若要了解如何以 Windows 10 API 運用這些功能,請參閱產生 3MF 套件教學課程。To learn how to utilize these features with Windows 10 APIs, see the Generate a 3MF package tutorial.

3D Builder App 可以開啟大部分熱門的 3D 格式,並另存為 .3mf 檔案。The 3D Builder app can open files of most popular 3D formats and save them as .3mf files. 在這個範例中,當檔案類型有所不同時,一種非常簡單的解決方案是開啟 3D Builder App 並提示使用者將匯入的資料另存為 .3mf 檔案,然後重新載入。In this example, where the file type could vary, a very simple solution is to open the 3D Builder app and prompt the user to save the imported data as a .3mf file and then reload it.

注意

除了轉換檔案格式之外,3D Builder 提供簡單的工具來編輯模型、新增顏色資料,以及執行其他列印特定作業,因此通常值得將它整合到處理 3D 列印的 app 中。In addition to converting file formats, 3D Builder provides simple tools to edit your models, add color data, and perform other print-specific operations, so it is often worth integrating into an app that deals with 3D printing.

    // 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 列印Repair model data for 3D printing

並非所有 3D 模型資料都可以列印,即使是 .3mf 類型也一樣。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, the model(s) to be printed must (each) 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. 不過,新式的軟體解決方案通常可將原始幾何檔案轉換為可列印的 3D 圖形。However, modern software solutions are often adequate for converting raw geometry to printable 3D shapes. 這稱為將模型「修復」**,它會在 OnFixClick 方法中完成。This is known as repairing the model and will be done in the OnFixClick method.

必須將 3D資料檔案轉換以實作 IRandomAccessStream,這可接著用來產生 Printing3DModel 物件。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();

Printing3DModel 物件現在已經修復且可供列印。The Printing3DModel object is now repaired and printable. 使用 SaveModelToPackageAsync 將模型指派到您建立類別時宣告的 Printing3D3MFPackage 物件。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);

}

執行列印工作︰建立 TaskRequested 處理常式Execute printing task: create a TaskRequested handler

稍後對使用者顯示 3D 列印對話方塊且使用者選擇開始列印時,您的 app 必須將所需的參數傳遞到 3D 列印管線。Later on, 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. 3D 列印 API 會引發 TaskRequested 事件。The 3D print API will raise the TaskRequested event. 您必須撰寫一個方法來適當地處理這個事件。You must write a method to handle this event appropriately. 如同以往,處理常式方法必須與其事件類型相同︰TaskRequested 事件有參數 Print3DManager (其傳送者物件的參考) 和會保存大部分相關資訊的 Print3DTaskRequestedEventArgs 物件。As always, the handler method must be of the same type as its event: The TaskRequested event has parameters Print3DManager (a reference to its sender object) and a Print3DTaskRequestedEventArgs object, which holds most of the relevant information.

private void MyTaskRequested(Print3DManager sender, Print3DTaskRequestedEventArgs args) {

這個方法的核心目的是使用 args 參數來將 Printing3D3MFPackage 向下傳送到管線。The core purpose of this method is to use the args parameter to send a Printing3D3MFPackage down the pipeline. Print3DTaskRequestedEventArgs 類型有一個屬性︰RequestThe Print3DTaskRequestedEventArgs type has one property: Request. 它是 Print3DTaskRequest 類型,並代表一個列印工作要求。It is of the type Print3DTaskRequest and represents one print job request. 它的方法 CreateTask 可讓程式為列印工作送出正確資訊,而且它會傳回向下傳遞到 3D 列印管線之 Print3DTask 物件的參考。Its method CreateTask allows the program to submit the correct information for your print job, and it returns a reference to the Print3DTask object which was sent down the 3D print pipeline.

CreateTask 具有下列輸入參數:列印工作名稱的字串、要使用之印表機的識別碼字串,及 Print3DTaskSourceRequestedHandler 委派。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. 當引發 3DTaskSourceRequested 事件時,會自動叫用委派 (這會由 API 本身完成)。The delegate is automatically invoked when the 3DTaskSourceRequested event is raised (this is done by the API itself). 要注意的重點是,這個委派在列印工作初始化時即已叫用,它會負責提供正確的 3D 列印封包。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 會接受一個參數,該參數提供要傳遞之資料的 Print3DTaskSourceRequestedArgs 物件。Print3DTaskSourceRequestedHandler takes one parameter, a Print3DTaskSourceRequestedArgs object which provides the data to be sent. 這個類別的唯一公用方法 SetSource 會接受要列印的封包。The one public method of this class, SetSource, accepts the package to be printed. 實作 Print3DTaskSourceRequestedHandler 委派,如下所示。Implement a Print3DTaskSourceRequestedHandler delegate as follows.

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

接著,使用新定義的委派 sourceHandler 呼叫 CreateTaskNext, call CreateTask, using the newly-defined delegate, sourceHandler.

// 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 會指派到在開頭宣告的類別變數。The returned Print3DTask is assigned to the class variable declared in the beginning. 您現在可以 (選擇性地) 使用此參考,來處理工作擲回的特定事件。You can now (optionally) use this reference to handle certain events thrown by the task.

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

注意

如果您希望將 Task_SubmittingTask_Completed 方法登錄到這些事件,您必須實作它們。You must implement a Task_Submitting and Task_Completed method if you wish to register them to these events.

執行列印工作︰開啟 3D 列印對話方塊Execute printing task: open 3D print dialog

所需的最終一段程式碼,是啟動 3D 列印對話方塊。The final piece of code needed is that which launches the 3D print dialog. 如同傳統的列印對話方塊視窗,3D 列印對話方塊提供數個最終列印選項,並讓使用者選取要使用的印表機 (無論是透過 USB 或網路連接)。Like a conventional printing dialog window, the 3D print dialog provides a number of last-minute printing options and allows the user to choose which printer to use (whether connected by USB or the network).

將您的 MyTaskRequested 方法向 TaskRequested 事件登錄。Register your 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;

登錄您的 TaskRequested 事件處理常式後,您可以叫用 ShowPrintUIAsync 方法,這會在目前的應用程式視窗中顯示 3D 列印對話方塊。After registering your 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();

最後,當 App 繼續控制時,解除登錄事件處理常式是很好的做法。Finally, it is a 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;
}

產生 3MF 套件Generate a 3MF package
3D 列印 UWP 範例3D printing UWP sample