AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
MeshSaver.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 using System.Collections.Generic;
6 using System.IO;
7 using UnityEngine;
8 
9 #if !UNITY_EDITOR && UNITY_WSA
10 using System.Threading.Tasks;
11 using Windows.Storage;
12 using Windows.Storage.Streams;
13 #endif
14 
15 namespace HoloToolkit.Unity.SpatialMapping
16 {
20  public static class MeshSaver
21  {
25  private static string fileExtension = ".room";
26 
30  public static string MeshFolderName
31  {
32  get
33  {
34 #if !UNITY_EDITOR && UNITY_WSA
35  return ApplicationData.Current.RoamingFolder.Path;
36 #else
37  return Application.persistentDataPath;
38 #endif
39  }
40  }
41 
49  public static string Save(string fileName, IEnumerable<MeshFilter> meshFilters)
50  {
51  if (string.IsNullOrEmpty(fileName))
52  {
53  throw new ArgumentException("Must specify a valid fileName.");
54  }
55 
56  if (meshFilters == null)
57  {
58  throw new ArgumentNullException("Value of meshFilters cannot be null.");
59  }
60 
61  // Create the mesh file.
62  String folderName = MeshFolderName;
63  Debug.Log(String.Format("Saving mesh file: {0}", Path.Combine(folderName, fileName + fileExtension)));
64 
65  using (Stream stream = OpenFileForWrite(folderName, fileName + fileExtension))
66  {
67  // Serialize and write the meshes to the file.
68  byte[] data = SimpleMeshSerializer.Serialize(meshFilters);
69  stream.Write(data, 0, data.Length);
70  stream.Flush();
71  }
72 
73  Debug.Log("Mesh file saved.");
74 
75  return Path.Combine(folderName, fileName + fileExtension);
76  }
77 
85  public static string Save(string fileName, IEnumerable<Mesh> meshes)
86  {
87  if (string.IsNullOrEmpty(fileName))
88  {
89  throw new ArgumentException("Must specify a valid fileName.");
90  }
91 
92  if (meshes == null)
93  {
94  throw new ArgumentNullException("Value of meshes cannot be null.");
95  }
96 
97  // Create the mesh file.
98  String folderName = MeshFolderName;
99  Debug.Log(String.Format("Saving mesh file: {0}", Path.Combine(folderName, fileName + fileExtension)));
100 
101  using (Stream stream = OpenFileForWrite(folderName, fileName + fileExtension))
102  {
103  // Serialize and write the meshes to the file.
104  byte[] data = SimpleMeshSerializer.Serialize(meshes);
105  stream.Write(data, 0, data.Length);
106  stream.Flush();
107  }
108 
109  Debug.Log("Mesh file saved.");
110 
111  return Path.Combine(folderName, fileName + fileExtension);
112  }
113 
120  public static IList<Mesh> Load(string fileName)
121  {
122  if (string.IsNullOrEmpty(fileName))
123  {
124  throw new ArgumentException("Must specify a valid fileName.");
125  }
126 
127  List<Mesh> meshes = new List<Mesh>();
128 
129  // Open the mesh file.
130  String folderName = MeshFolderName;
131  Debug.Log(String.Format("Loading mesh file: {0}", Path.Combine(folderName, fileName + fileExtension)));
132 
133  using (Stream stream = OpenFileForRead(folderName, fileName + fileExtension))
134  {
135  // Read the file and deserialize the meshes.
136  byte[] data = new byte[stream.Length];
137  stream.Read(data, 0, data.Length);
138 
139  meshes.AddRange(SimpleMeshSerializer.Deserialize(data));
140  }
141 
142  Debug.Log("Mesh file loaded.");
143 
144  return meshes;
145  }
146 
153  private static Stream OpenFileForRead(string folderName, string fileName)
154  {
155  Stream stream = null;
156 
157 #if !UNITY_EDITOR && UNITY_WSA
158  Task<Task> task = Task<Task>.Factory.StartNew(
159  async () =>
160  {
161  StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(folderName);
162  StorageFile file = await folder.GetFileAsync(fileName);
163  IRandomAccessStreamWithContentType randomAccessStream = await file.OpenReadAsync();
164  stream = randomAccessStream.AsStreamForRead();
165  });
166  task.Wait();
167  task.Result.Wait();
168 #else
169  stream = new FileStream(Path.Combine(folderName, fileName), FileMode.Open, FileAccess.Read);
170 #endif
171  return stream;
172  }
173 
181  private static Stream OpenFileForWrite(string folderName, string fileName)
182  {
183  Stream stream = null;
184 
185 #if !UNITY_EDITOR && UNITY_WSA
186  Task<Task> task = Task<Task>.Factory.StartNew(
187  async () =>
188  {
189  StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(folderName);
190  StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
191  IRandomAccessStream randomAccessStream = await file.OpenAsync(FileAccessMode.ReadWrite);
192  stream = randomAccessStream.AsStreamForWrite();
193  });
194  task.Wait();
195  task.Result.Wait();
196 #else
197  stream = new FileStream(Path.Combine(folderName, fileName), FileMode.Create, FileAccess.Write);
198 #endif
199  return stream;
200  }
201  }
202 }
MeshSaver is a static class containing methods used for saving and loading meshes.
Definition: MeshSaver.cs:20
SimpleMeshSerializer converts a UnityEngine.Mesh object to and from an array of bytes. This class saves minimal mesh data (vertices and triangle indices) in the following format: File header: vertex count (32 bit integer), triangle count (32 bit integer) Vertex list: vertex.x, vertex.y, vertex.z (all 32 bit float) Triangle index list: 32 bit integers
static IEnumerable< Mesh > Deserialize(byte[] data)
Deserializes a list of Mesh objects from the provided byte array.
static IList< Mesh > Load(string fileName)
Loads the specified mesh file.
Definition: MeshSaver.cs:120
static byte [] Serialize(IEnumerable< Mesh > meshes)
Serializes a list of Mesh objects into a byte array.
static string Save(string fileName, IEnumerable< MeshFilter > meshFilters)
Transforms all the mesh vertices into world position before saving to file.
Definition: MeshSaver.cs:49
static string Save(string fileName, IEnumerable< Mesh > meshes)
Saves the provided meshes to the specified file.
Definition: MeshSaver.cs:85