Choosing a format for 3D data

Viewing an apartment in 3D on the web

Using Unity3D, we built a 3D model viewer for the web and iPad. Unlike many Unity applications, our models live on our server and are dynamically loaded into the Unity viewer when the user wants to view that model.

In addition to the Unity viewer, our models are also used by our backend Lua-based processing pipeline. In this blog post, we'll explain what format we picked for storing models and why we picked it.

What qualities do we care about?

There are a large number of possible formats. For example, Sketchfab supports 25 native formats: ".blend, .obj, .dae, .ply, and much more!"

When we were thinking about format, a couple things were important to us:

File size - The larger the file, the longer it takes to download.

Loading speed - We can't see the model until it is done loading.

Compatibility - In addition to Unity (C#), we also have a Node.js web app, an iPad app, and a Lua-based backend. All of these areas needed to be able to interact with the model appropriately.

Control - Would we be able to make changes easily?

Readability - Can we open the file in a text editor and read it easily?

Three formats walk into a bar...

Unity's proprietary format for streaming assets. Like a zip file, one AssetBundle can contain multiple assets of different file types. Unlike a zip file, AssetBundles cannot easily be "unzipped". AssetBundles have a small file size and load speedily into Unity. AssetBundles can be cached to Unity's cache folder on the client. Bundles built for web cannot be loaded on iOS and vice versa. A Unity Pro license and a Unity iOS Advanced license are required for building web and iOS bundles, respectively. iOS bundles must be built on a Mac.

An open format, OBJs are considered to be "universally accepted". OBJs are simple text files that are easy to open and read. Raw data from our 3D scanner comes in this format. There are several scipts forloading a Unity modelfrom an OBJ. OBJs are large because each line represents one thing — a vertex, a face, etc. Loading an OBJ into Unity takes a long time.

Google's open format for storing and exchanging structured data across languages and platforms. Usually compared to XML, JSON, and more recently, Thrift, protocol buffers are compact and efficient — "think XML, but smaller, faster, and simpler." There are libraries for protocol buffers in many languages and protocol buffers need an external, user-defined schema to serialize and deserialize data.

Protocol Buffers win the day

In the end, we picked protocol buffers. Although they were only infrequently the best, they were never the worst. Next time we'll talk about some unexpected hiccups with using protobufs, Unity, and iOS.