3MF パッケージの生成Generate a 3MF package

重要な APIImportant APIs

このガイドでは、3D Manufacturing Format (3MF) ドキュメントの構造について説明し、その作成方法と Windows.Graphics.Printing3D API による操作について説明します。This guide describes the structure of the 3D Manufacturing Format document and how it can be created and manipulated with the Windows.Graphics.Printing3D API.

3MF の概要What is 3MF?

3D Manufacturing Format (3MF) は、製造 (3D 印刷) 目的のために、XML を使って 3D モデルの外観と構造を記述するための規則のセットです。The 3D Manufacturing Format is a set of conventions for using XML to describe the appearance and structure of 3D models for the purpose of manufacturing (3D printing). 3MF ではパーツ (必須なパーツとオプションのパーツがあります) のセットとそのリレーションシップを定義しています。そのねらいは 3D 製造デバイスのために必要なすべての情報を提供することです。It defines a set of parts (some required and some optional) and their relationships, with the goal of providing all necessary information to a 3D manufacturing device. 3MF に準拠したデータセットは .3mf 拡張子を持つファイルとして保存できます。A data set that adheres to the 3D Manufacturing Format can be saved as a file with the .3mf extension.

Windows 10 で、 Printing3D3MFPackage クラス、 Windows.Graphics.Printing3D名前空間は、1 つ .3mf ファイルとする他のクラスのマップに似ています、ファイルの XML 要素を特定します。In Windows 10, the Printing3D3MFPackage class in the Windows.Graphics.Printing3D namespace is analogous to a single .3mf file, and other classes map to the particular XML elements in the file. このガイドでは、3MF ドキュメントの主なパーツのそれぞれの作成方法とプログラムによる設定方法、3MF の素材の拡張の利用方法、Printing3D3MFPackage オブジェクトを変換して .3mf ファイルとして保存する方法について説明します。This guide describes how each of the main parts of a 3MF document can be created and set programmatically, how the 3MF Materials Extension can be utilized, and how a Printing3D3MFPackage object can be converted and saved as a .3mf file. 3MF および 3MF 素材の拡張の標準について詳しくは、「3MF の仕様」をご覧ください。For more information on the standards of 3MF or the 3MF Materials Extension, see the 3MF Specification.

3MF 構造体の主なクラスCore classes in the 3MF structure

Printing3D3MFPackage クラスは完全な 3MF ドキュメントを表します。3MF ドキュメントの中心となるのは、Printing3DModel クラスで表される、モデル パーツです。The Printing3D3MFPackage class represents a complete 3MF document, and at the core of a 3MF document is its model part, represented by the Printing3DModel class. 3D モデルを指定する情報のほとんどは Printing3DModel クラスのプロパティおよびその基になるクラスのプロパティを設定して保存されます。Most of the information we wish to specify about a 3D model will be stored by setting the properties of the Printing3DModel class and the properties of their underlying classes.

var localPackage = new Printing3D3MFPackage();
var model = new Printing3DModel();
// specify scaling units for model data
model.Unit = Printing3DModelUnit.Millimeter;


3MF ドキュメントのモデル パーツは、Metadata プロパティに保存される文字列のキー/値ペアの形式でメタデータを保持できます。The model part of a 3MF document can hold metadata in the form of key/value pairs of strings stored in the Metadata property. さまざまな定義済みの名前のメタデータがありますが、他のペアをパーツの拡張として追加することも可能です (詳しくは、「3MF の仕様」に記載されています)。There are a number of predefined names of metadata, but other pairs can be added as part of an extension (described in more detail in the 3MF specification). メタデータの処理方法の決定はパッケージの受信者 (3D 製造デバイス) に依存しますが、できるだけ多くの基本情報を 3MF パッケージに含めることが望ましい方法です。It is up to the receiver of the package (a 3D manufacturing device) to determine whether and how to handle metadata, but it is good practice to include as much basic info as possible in the 3MF package:

model.Metadata.Add("Title", "Cube");
model.Metadata.Add("Designer", "John Smith");
model.Metadata.Add("CreationDate", "1/1/2016");

メッシュ データMesh data

このガイドにおいては、メッシュとは、頂点のセットから作成される 3 次元形状のボディを意味します (必ずしも 1 つの立体として見えるとは限りません)。In the context of this guide, a mesh is a body of 3-dimensional geometry constructed from a single set of vertices (though it does not have to appear as a single solid). メッシュ パーツは Printing3DMesh クラスで表されます。A mesh part is represented by the Printing3DMesh class. 有効なメッシュ オブジェクトは、すべての頂点の位置、およびいくつかの頂点のセットの間に存在する三角形の表面についての情報を含む必要があります。A valid mesh object must contain information about the location of all of its vertices as well as all the triangle faces that exist between certain sets of vertices.

次のメソッドは、メッシュに頂点を追加して、3D 空間での位置を与えます。The following method adds vertices to a mesh and then gives them locations in 3D space:

private async Task GetVerticesAsync(Printing3DMesh mesh) {
    Printing3DBufferDescription description;

    description.Format = Printing3DBufferFormat.Printing3DDouble;

    // have 3 xyz values
    description.Stride = 3;

    // have 8 vertices in all in this mesh
    mesh.CreateVertexPositions(sizeof(double) * 3 * 8);
    mesh.VertexPositionsDescription = description;

    // set the locations (in 3D coordinate space) of each vertex
    using (var stream = mesh.GetVertexPositions().AsStream()) {
        double[] vertices =
            0, 0, 0,
            10, 0, 0,
            0, 10, 0,
            10, 10, 0,
            0, 0, 10,
            10, 0, 10,
            0, 10, 10,
            10, 10, 10,

        // convert vertex data to a byte array
        byte[] vertexData = vertices.SelectMany(v => BitConverter.GetBytes(v)).ToArray();

        // write the locations to each vertex
        await stream.WriteAsync(vertexData, 0, vertexData.Length);
    // update vertex count: 8 vertices in the cube
    mesh.VertexCount = 8;

次のメソッドは、頂点間で描画されるすべての三角形を定義します。The next method defines all of the triangles to be drawn across these vertices:

private static async Task SetTriangleIndicesAsync(Printing3DMesh mesh) {

    Printing3DBufferDescription description;

    description.Format = Printing3DBufferFormat.Printing3DUInt;
    // 3 vertex indices
    description.Stride = 3;
    // 12 triangles in all in the cube
    mesh.IndexCount = 12;

    mesh.TriangleIndicesDescription = description;

    // allocate space for 12 triangles
    mesh.CreateTriangleIndices(sizeof(UInt32) * 3 * 12);

    // get a datastream of the triangle indices (should be blank at this point)
    var stream2 = mesh.GetTriangleIndices().AsStream();
        // define a set of triangle indices: each row is one triangle. The values in each row
        // correspond to the index of the vertex. 
        UInt32[] indices =
            1, 0, 2,
            1, 2, 3,
            0, 1, 5,
            0, 5, 4,
            1, 3, 7,
            1, 7, 5,
            2, 7, 3,
            2, 6, 7,
            0, 6, 2,
            0, 4, 6,
            6, 5, 7,
            4, 5, 6,
        // convert index data to byte array
        var vertexData = indices.SelectMany(v => BitConverter.GetBytes(v)).ToArray();
        var len = vertexData.Length;
        // write index data to the triangle indices stream
        await stream2.WriteAsync(vertexData, 0, vertexData.Length);



すべての三角形では、(三角形をメッシュ オブジェクトの外側から見て) 反時計回りでインデックスを定義する必要があります。これにより、表面の法線ベクトルが外側に向きます。All triangles must have their indices defined in counter-clockwise order (when viewing the triangle from outside of the mesh object), so that their face-normal vectors point outward.

Printing3DMesh オブジェクトが頂点と三角形の有効なセットを含む場合、それはモデルの Meshes プロパティに追加される必要があります。When a Printing3DMesh object contains valid sets of vertices and triangles, it should then be added to the model's Meshes property. パッケージに含まれるすべての Printing3DMesh オブジェクトは、Printing3DModel クラスの Meshes プロパティの下に保存される必要があります。All Printing3DMesh objects in a package must be stored under the Meshes property of the Printing3DModel class.

// add the mesh to the model

素材の作成Create materials

3D モデルは複数の素材のデータを保持できます。A 3D model can hold data for multiple materials. この規則は、1 回の印刷ジョブで複数の素材を使用できる 3D 製造デバイスを活用するためのものです。This convention is intended to take advantage of 3D manufacturing devices that can use multiple materials on a single print job. また複数の種類の素材グループがあり、それぞれがさまざまな個々の素材をサポートできます。There are also multiple types of material gropus, each one capable of supporting a number of different individual materals. 各素材グループは一意の参照 ID 番号を持つ必要があります。グループ内の各素材も一意の ID を持つ必要があります。Each material group must have a unique reference id number, and each material within that group must also have a unique id.

これにより、モデル内の別のメッシュ オブジェクトがこれらの素材を参照できます。The different mesh objects within a model can then reference these materials. さらに、各メッシュの個々の三角形は、別の素材を指定できます。Furthermore, individual triangles on each mesh can specify different materials. また、1 つの三角形内で別の素材が表され、三角形の各頂点が別の素材に割り当てられて、表面の素材はそれらのグラデーションとして計算されることさえも可能です。Further still, different materials can even be represented within a single triangle, with each triangle vertex having a different material assigned to it and the face material calculated as the gradient between them.

このガイドではまず、異なる種類の素材をそれぞれの素材グループ内に作成して、それをモデル オブジェクトのリソースとして保存する方法を示します。This guide will first show how to create different kinds of materials within their respective material groups and store them as resources on the model object. 次に、個々のメッシュと個々の三角形に別の素材を割り当てます。Then, we will go about assigning different materials to individual meshes and individual triangles.

Base materialsBase materials

既定の素材の種類は Base Material です。これは Color Material 値 (下記を参照) と名前属性を持ちます。これは使用する素材の種類を指定するために使用します。The default material type is Base Material, which has both a Color Material value (described below) and a name attribute that is intended to specify the type of material to use.

// add material group
// all material indices need to start from 1: 0 is a reserved id
// create new base materialgroup with id = 1
var baseMaterialGroup = new Printing3DBaseMaterialGroup(1);

// create color objects
// 'A' should be 255 if alpha = 100%
var darkBlue = Windows.UI.Color.FromArgb(255, 20, 20, 90);
var orange = Windows.UI.Color.FromArgb(255, 250, 120, 45);
var teal = Windows.UI.Color.FromArgb(255, 1, 250, 200);

// create new ColorMaterials, assigning color objects
var colrMat = new Printing3DColorMaterial();
colrMat.Color = darkBlue;

var colrMat2 = new Printing3DColorMaterial();
colrMat2.Color = orange;

var colrMat3 = new Printing3DColorMaterial();
colrMat3.Color = teal;

// setup new materials using the ColorMaterial objects
// set desired material type in the Name property
var baseMaterial = new Printing3DBaseMaterial {
    Name = Printing3DBaseMaterial.Pla,
    Color = colrMat

var baseMaterial2 = new Printing3DBaseMaterial {
    Name = Printing3DBaseMaterial.Abs,
    Color = colrMat2

// add base materials to the basematerialgroup

// material group index 0
// material group index 1

// add material group to the basegroups property of the model


 3D の製造デバイスでは、仮想の数量単価型の要素が、3MF に保存されている、使用可能な物理マテリアルのマップを決定します。 The 3D manufacturing device will determine which available physical materials map to which virtual material elements stored in the 3MF. 素材のマッピングは 1:1 とは限りません。3D プリンターが 1 つの素材のみを使用できる場合、オブジェクトや表面が別の素材に割り当てられている場合でも、全モデルをその素材で印刷します。Material mapping doesn't have to be 1:1: if a 3D printer only uses one material, it will print the whole model in that material, regardless of which objects or faces were assigned different materials.

Color MaterialsColor materials

Color MaterialsBase Materials に似ていますが、名前は含まれません。Color Materials are similar to Base Materials, but they do not contain a name. そのため、マシンが使用する素材の種類を指定できません。Thus, they give no instructions as to what type of material should be used by the machine. 色のデータのみを保持し、マシンが素材の種類を選択します (マシンがユーザーに選択を求める場合もあります)。They hold only color data, and let the machine choose the material type (and the machine may then prompt the user to choose). 次のコードでは、以前のメソッドからの colrMat オブジェクトが使用されています。In the code below, the colrMat objects from the previous method are used on their own.

// add ColorMaterials to the Color Material Group (with id 2)
var colorGroup = new Printing3DColorMaterialGroup(2);

// add the previous ColorMaterial objects to this ColorMaterialGroup

// add colorGroup to the ColorGroups property on the model

複合素材Composite materials

Composite Materials は製造デバイスに、さまざまな Base Materials を一定の組み合わせで使用するように指示します。Composite Materials simply instruct the manufacturing device to use a uniform mixture of different Base Materials. Composite Material Group は材料を使う 1 つの Base Material Group のみを参照する必要があります。Each Composite Material Group must reference exactly one Base Material Group from which to draw ingredients. さらに、このグループ内で利用できる Base MaterialsMaterial Indices の一覧にリストされている必要があります。これは比率を指定する際に各 Composite Material によって参照されます (すべての Composite Material は単に Base Materials の比率です)。Additonally, the Base Materials within this group that are to be made available must be listed out in a Material Indices list, which each Composite Material will then reference when specifying the ratios (every Composite Material is simply a ratio of Base Materials).

// CompositeGroups
// create new composite material group with id = 3
var compositeGroup = new Printing3DCompositeMaterialGroup(3);

// indices point to base materials in BaseMaterialGroup with id =1

// create new composite materials
var compMat = new Printing3DCompositeMaterial();
// fraction adds to 1.0
compMat.Values.Add(0.2); // .2 of first base material in BaseMaterialGroup 1
compMat.Values.Add(0.8); // .8 of second base material in BaseMaterialGroup 1

var compMat2 = new Printing3DCompositeMaterial();
// fraction adds to 1.0

var compMat3 = new Printing3DCompositeMaterial();
// fraction adds to 1.0

var compMat4 = new Printing3DCompositeMaterial();
// fraction adds to 1.0

// add composites to group

// add group to model

テクスチャ座標の素材Texture coordinate materials

3MF は 2D 画像を使って 3D モデルの表面に色を付けることをサポートします。3MF supports the use of 2D images to color the surfaces of 3D models. これによりモデルは、三角形の表面ごとに、より多くの色データを伝えることができます (三角形の頂点ごとに 1 つの色の値を持つ場合と比べて)。This way, the model can convey much more color data per triangle face (as opposed to having just one color value per triangle vertex). Color Materials と同様に、テクスチャ座標の素材は色データのみを伝えます。Like Color Materials, texture coordinate materials only convery color data. 2D テクスチャを使うには、まずテクスチャ リソースを宣言する必要があります。To use a 2D texture, a texture resource must first be declared:

// texture resource setup
Printing3DTextureResource texResource = new Printing3DTextureResource();
// name conveys the path within the 3MF document
texResource.Name = "/3D/Texture/msLogo.png";

// in this case, we reference texture data in the sample appx, convert it to 
// an IRandomAccessStream, and assign it as the TextureData
Uri texUri = new Uri("ms-appx:///Assets/msLogo.png");
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(texUri);
IRandomAccessStreamWithContentType iRandomAccessStreamWithContentType = await file.OpenReadAsync();
texResource.TextureData = iRandomAccessStreamWithContentType;
// add this testure resource to the 3MF Package

// assign this texture resource to a Printing3DModelTexture
var modelTexture = new Printing3DModelTexture();
modelTexture.TextureResource = texResource;


テクスチャ データは、パッケージ内のモデル パーツでなく、3MF パッケージ自体に属しています。Texture data belongs to the 3MF Package itself, not to the model part within the package.

次に Texture3Coord Materials を記入する必要があります。Next, we must fill out Texture3Coord Materials. これらはそれぞれテクスチャ リソースを参照し、画像の特定の点を (UV 座標で) 指定します。Each of these references a texture resource and specifies a particular point on the image (in UV coordinates).

// texture2Coord Group
// create new Texture2CoordMaterialGroup with id = 4
var tex2CoordGroup = new Printing3DTexture2CoordMaterialGroup(4);

// create texture materials:
// set up four tex2coordmaterial objects with four (u,v) pairs, 
// mapping to each corner of the image:

var tex2CoordMaterial = new Printing3DTexture2CoordMaterial();
tex2CoordMaterial.U = 0.0;
tex2CoordMaterial.V = 1.0;

var tex2CoordMaterial2 = new Printing3DTexture2CoordMaterial();
tex2CoordMaterial2.U = 1.0;
tex2CoordMaterial2.V = 1.0;

var tex2CoordMaterial3 = new Printing3DTexture2CoordMaterial();
tex2CoordMaterial3.U = 0.0;
tex2CoordMaterial3.V = 0.0;

var tex2CoordMaterial4 = new Printing3DTexture2CoordMaterial();
tex2CoordMaterial4.U = 1.0;
tex2CoordMaterial4.V = 0.0;

// add our Printing3DModelTexture to the Texture property of the group
tex2CoordGroup.Texture = modelTexture;

// add metadata about the texture so that u,v values can be used
model.Metadata.Add("tex4", "/3D/Texture/msLogo.png");
// add group to groups on the model's material

素材を表面にマップMap materials to faces

素材と各三角形の頂点のマッピングを指定するには、モデルのメッシュ オブジェクトにさらに処理を行う必要があります (モデルに複数のメッシュが含まれる場合、それぞれに素材が割り当てられる必要があります)。In order to dictate which materials are mapped to which vertices on each triangle, we must do some more work on the mesh object of our model (if a model contains multiple meshes, they must each have their materials assigned separately). 既に説明したように、素材は頂点ごと、三角形ごとに割り当てられます。As mentioned above, materials are assigned per-vertex, per-triangle. 次のコードを参照して、この情報の入力と解釈の方法を確認します。Refer to the code below to see how this information is entered and interpreted.

private static async Task SetMaterialIndicesAsync(Printing3DMesh mesh) {
    // declare a description of the material indices
    Printing3DBufferDescription description;
    description.Format = Printing3DBufferFormat.Printing3DUInt;
    // 4 indices for material description per triangle
    description.Stride = 4;
    // 12 triangles total
    mesh.IndexCount = 12;
    mesh.TriangleMaterialIndicesDescription = description;

    // create space for storing this data
    mesh.CreateTriangleMaterialIndices(sizeof(UInt32) * 4 * 12);

        // each row is a triangle face (in the order they were created)
        // first column is the id of the material group, last 3 columns show which material id (within that group)
        // maps to each triangle vertex (in the order they were listed when creating triangles)
        UInt32[] indices =
            // base materials:
            // in  the BaseMaterialGroup (id=1), the BaseMaterial with id=0 will be applied to these triangle vertices
            1, 0, 0, 0, 
            1, 0, 0, 0,
            // color materials:
            // in the ColorMaterialGroup (id=2), the ColorMaterials with these ids will be applied to these triangle vertices
            2, 1, 1, 1,
            2, 1, 1, 1,
            2, 0, 0, 0,
            2, 0, 0, 0,
            2, 0, 1, 2,
            2, 1, 0, 2,
            // composite materials:
            // in the CompositeMaterialGroup (id=3), the CompositeMaterial with id=0 will be applied to these triangles
            // texture materials:
            // in the Texture2CoordMaterialGroup (id=4), each texture coordinate is mapped to the appropriate vertex on these
            // two adjacent triangle faces, so that the square face they create displays the original rectangular image
            4, 0, 3, 1,
            4, 2, 3, 0,

        // get the current (unassigned) vertex data as a stream and write our new 'indices' data to it.
        var stream = mesh.GetTriangleMaterialIndices().AsStream();
        var vertexData = indices.SelectMany(v => BitConverter.GetBytes(v)).ToArray();
        var len = vertexData.Length;
        await stream.WriteAsync(vertexData, 0, vertexData.Length);

Component とビルドComponents and build

Component 構造体により、ユーザーは印刷可能な 3D モデルに複数のメッシュ オブジェクトを配置できます。The component structure allows the user to place more than one mesh object in a printable 3D model. Printing3DComponent オブジェクトには、1 つのメッシュと他のコンポーネントへの参照のリストが含まれています。A Printing3DComponent object contains a single mesh and a list of references to other components. これは実際には、Printing3DComponentWithMatrix オブジェクトのリストです。This is actually a list of Printing3DComponentWithMatrix objects. Printing3DComponentWithMatrix オブジェクトには Printing3DComponent が含まれ、また重要なことに、メッシュと Printing3DComponent に含まれるコンポーネントに適用される変換マトリックスが含まれます。Printing3DComponentWithMatrix objects each contain a Printing3DComponent and, importantly, a transform matrix that applies to the mesh and contained components of said Printing3DComponent.

たとえば、自動車のモデルは、車のボディのメッシュを保持する、1 つの "ボディ" Printing3DComponent から構成されることができます。For example, a model of a car might consist of a "Body" Printing3DComponent that holds the mesh for the car's body. この場合、"ボディ" コンポーネントには、4 つの異なる Printing3DComponentWithMatrix オブジェクトへの参照が含まれ、そのすべてが、"車輪" メッシュを持つ、同じ Printing3DComponent を参照し、4 つの異なる変換マトリックスを含みます (これにより、車輪を車のボディの 4 つの異なる位置にマッピングします)。The "Body" component may then contain references to four different Printing3DComponentWithMatrix objects, which all reference the same Printing3DComponent with the "Wheel" mesh and contain four different transform matrices (mapping the wheels to four different positions on the car's body). このシナリオでは、最終製品には合計 5 つのメッシュが含まれる場合でも、"ボディ" メッシュと "車輪" メッシュはそれぞれ 1 度だけ保存される必要があります。In this scenario, the "Body" mesh and "Wheel" mesh would each only need to be stored once, even though the final product would feature five meshes in total.

すべての Printing3DComponent オブジェクトはモデルの Components プロパティで直接参照される必要があります。All Printing3DComponent objects must be directly referenced in the model's Components property. 印刷ジョブで使用される 1 つの特定のコンポーネントは Build プロパティに保存されています。The one particular component that is to be used in the printing job is stored in the Build Property.

// create new component
Printing3DComponent component = new Printing3DComponent();

// assign mesh to the component's mesh
component.Mesh = mesh;

// add component to the model's list of all used components
// a model can have references to multiple components

// create the transform matrix
var componentWithMatrix = new Printing3DComponentWithMatrix();
// assign component to this componentwithmatrix
componentWithMatrix.Component = component;

// create an identity matrix
var identityMatrix = Matrix4x4.Identity;

// use the identity matrix as the transform matrix (no transformation)
componentWithMatrix.Matrix = identityMatrix;

// add component to the build property.

パッケージの保存Save package

素材とコンポーネントを定義したモデルが完成したので、それをパッケージに保存します。Now that we have a model, with defined materials and components, we can save it to the package.

// save the model to the package:
await localPackage.SaveModelToPackageAsync(model);
// get the model stream
var modelStream = localPackage.ModelPart;

// fix any textures in the model file
localPackage.ModelPart = await FixTextureContentType(modelStream);

ここでは、アプリ内から印刷ジョブを開始するか (「アプリからの 3D 印刷」をご覧ください)、またはこの Printing3D3MFPackage を .3mf ファイルとして保存します。From here, we can either initiate a print job within the app (see 3D printing from your app), or save this Printing3D3MFPackage as a .3mf file.

次のメソッドは、完成した Printing3D3MFPackage を取得して、そのデータを .3mf ファイルに保存します。The following method takes a finished Printing3D3MFPackage and saves its data to a .3mf file.

private async void SaveTo3mf(Printing3D3MFPackage localPackage) {

    // prompt the user to choose a location to save the file to
    FileSavePicker savePicker = new FileSavePicker();
    savePicker.DefaultFileExtension = ".3mf";
    savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
    savePicker.FileTypeChoices.Add("3MF File", new[] { ".3mf" });
    var storageFile = await savePicker.PickSaveFileAsync();
    if (storageFile == null) {

    // save the 3MF Package to an IRandomAccessStream
    using (var stream = await localPackage.SaveAsync()) {
        // go to the beginning of the stream

        // read from the file stream and write to a buffer
        using (var dataReader = new DataReader(stream)) {
            await dataReader.LoadAsync((uint)stream.Size);
            var buffer = dataReader.ReadBuffer((uint)stream.Size);

            // write from the buffer to the storagefile specified
            await FileIO.WriteBufferAsync(storageFile, buffer);

アプリの 3D 印刷3D printing from your app
3D 印刷 UWP サンプル3D printing UWP sample