AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SimpleMeshSerializer.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.Collections.Generic;
5 using System.IO;
6 using UnityEngine;
7 using SysDiag = System.Diagnostics;
8 
9 namespace HoloToolkit.Unity.SpatialMapping
10 {
18  public static class SimpleMeshSerializer
19  {
23  private static int HeaderSize = sizeof(int) * 2;
24 
30  public static byte[] Serialize(IEnumerable<Mesh> meshes)
31  {
32  byte[] data;
33 
34  using (MemoryStream stream = new MemoryStream())
35  {
36  using (BinaryWriter writer = new BinaryWriter(stream))
37  {
38  foreach (Mesh mesh in meshes)
39  {
40  WriteMesh(writer, mesh);
41  }
42 
43  stream.Position = 0;
44  data = new byte[stream.Length];
45  stream.Read(data, 0, data.Length);
46  }
47  }
48 
49  return data;
50  }
51 
60  public static byte[] Serialize(IEnumerable<MeshFilter> meshes, Transform secondarySpace = null)
61  {
62  byte[] data = null;
63 
64  using (MemoryStream stream = new MemoryStream())
65  {
66  using (BinaryWriter writer = new BinaryWriter(stream))
67  {
68  foreach (MeshFilter meshFilter in meshes)
69  {
70  WriteMesh(writer, meshFilter.sharedMesh, meshFilter.transform, secondarySpace);
71  }
72 
73  stream.Position = 0;
74  data = new byte[stream.Length];
75  stream.Read(data, 0, data.Length);
76  }
77  }
78 
79  return data;
80  }
81 
87  public static IEnumerable<Mesh> Deserialize(byte[] data)
88  {
89  List<Mesh> meshes = new List<Mesh>();
90 
91  using (MemoryStream stream = new MemoryStream(data))
92  {
93  using (BinaryReader reader = new BinaryReader(stream))
94  {
95  while (reader.BaseStream.Length - reader.BaseStream.Position >= HeaderSize)
96  {
97  meshes.Add(ReadMesh(reader));
98  }
99  }
100  }
101 
102  return meshes;
103  }
104 
112  private static void WriteMesh(BinaryWriter writer, Mesh mesh, Transform transform = null, Transform secondarySpace = null)
113  {
114  SysDiag.Debug.Assert(writer != null);
115 
116  // Write the mesh data.
117  WriteMeshHeader(writer, mesh.vertexCount, mesh.triangles.Length);
118  WriteVertices(writer, mesh.vertices, transform, secondarySpace);
119  WriteTriangleIndicies(writer, mesh.triangles);
120  }
121 
127  private static Mesh ReadMesh(BinaryReader reader)
128  {
129  SysDiag.Debug.Assert(reader != null);
130 
131  int vertexCount = 0;
132  int triangleIndexCount = 0;
133 
134  // Read the mesh data.
135  ReadMeshHeader(reader, out vertexCount, out triangleIndexCount);
136  Vector3[] vertices = ReadVertices(reader, vertexCount);
137  int[] triangleIndices = ReadTriangleIndicies(reader, triangleIndexCount);
138 
139  // Create the mesh.
140  Mesh mesh = new Mesh();
141  mesh.vertices = vertices;
142  mesh.triangles = triangleIndices;
143  // Reconstruct the normals from the vertices and triangles.
144  mesh.RecalculateNormals();
145 
146  return mesh;
147  }
148 
155  private static void WriteMeshHeader(BinaryWriter writer, int vertexCount, int triangleIndexCount)
156  {
157  SysDiag.Debug.Assert(writer != null);
158 
159  writer.Write(vertexCount);
160  writer.Write(triangleIndexCount);
161 
162  }
163 
170  private static void ReadMeshHeader(BinaryReader reader, out int vertexCount, out int triangleIndexCount)
171  {
172  SysDiag.Debug.Assert(reader != null);
173 
174  vertexCount = reader.ReadInt32();
175  triangleIndexCount = reader.ReadInt32();
176  }
177 
185  private static void WriteVertices(BinaryWriter writer, Vector3[] vertices, Transform transform = null, Transform secondarySpace = null)
186  {
187  SysDiag.Debug.Assert(writer != null);
188 
189  if (transform != null)
190  {
191  for (int v = 0, vLength = vertices.Length; v < vLength; ++v)
192  {
193  Vector3 vertex = transform.TransformPoint(vertices[v]);
194  if (secondarySpace != null)
195  {
196  vertex = secondarySpace.InverseTransformPoint(vertex);
197  }
198  writer.Write(vertex.x);
199  writer.Write(vertex.y);
200  writer.Write(vertex.z);
201  }
202  }
203  else
204  {
205  foreach (Vector3 vertex in vertices)
206  {
207  writer.Write(vertex.x);
208  writer.Write(vertex.y);
209  writer.Write(vertex.z);
210  }
211  }
212  }
213 
220  private static Vector3[] ReadVertices(BinaryReader reader, int vertexCount)
221  {
222  SysDiag.Debug.Assert(reader != null);
223 
224  Vector3[] vertices = new Vector3[vertexCount];
225 
226  for (int i = 0; i < vertices.Length; i++)
227  {
228  vertices[i] = new Vector3(reader.ReadSingle(),
229  reader.ReadSingle(),
230  reader.ReadSingle());
231  }
232 
233  return vertices;
234  }
235 
241  private static void WriteTriangleIndicies(BinaryWriter writer, int[] triangleIndices)
242  {
243  SysDiag.Debug.Assert(writer != null);
244 
245  foreach (int index in triangleIndices)
246  {
247  writer.Write(index);
248  }
249  }
250 
257  private static int[] ReadTriangleIndicies(BinaryReader reader, int triangleIndexCount)
258  {
259  SysDiag.Debug.Assert(reader != null);
260 
261  int[] triangleIndices = new int[triangleIndexCount];
262 
263  for (int i = 0; i < triangleIndices.Length; i++)
264  {
265  triangleIndices[i] = reader.ReadInt32();
266  }
267 
268  return triangleIndices;
269  }
270  }
271 }
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 byte [] Serialize(IEnumerable< MeshFilter > meshes, Transform secondarySpace=null)
Serializes a list of MeshFilter objects into a byte array. Transforms vertices into world space befor...
static IEnumerable< Mesh > Deserialize(byte[] data)
Deserializes a list of Mesh objects from the provided byte array.
static byte [] Serialize(IEnumerable< Mesh > meshes)
Serializes a list of Mesh objects into a byte array.